home *** CD-ROM | disk | FTP | other *** search
/ Delphi 2 - Developers' Solutions / Delphi 2 Developers' Solutions.iso / dds / chap11 / howto05 / cciccpop.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-06-12  |  94.0 KB  |  2,656 lines

  1. unit Cciccpop;
  2.  
  3. interface
  4.  
  5. uses
  6.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  7.   Forms, Dialogs, ExtCtrls, StdCtrls, Buttons, Menus, FileCtrl, CCWSock, CCICCInf,
  8.   CCICCPrf, IniFiles, Gauges , CCUUCode, CCiccfrm;
  9.  
  10. const
  11.     The_Alphabet : array[ 0 .. 63 ] of char  =
  12.      'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  13. type
  14.   TMIMEErrorEvent = procedure( ErrorCode : Integer; ErrorMessage : String )
  15.    of object;
  16.   TMIMEUpdateEvent = procedure( BytesCompleted , TotalBytes : LongInt )
  17.    of object;
  18.   TMIMECodingObject = class( TWinControl )
  19.   private
  20.     FOnMIMEErrorOccurred  : TMIMEErrorEvent;
  21.     FOnMIMEUpdateOccurred : TMIMEUpdateEvent;
  22.   public
  23.     OutputString       : String;
  24.     The_Accumulator    : LongInt;
  25.     Total_Bits_Shifted : SmallInt;
  26.     BytesDone ,
  27.     BytesToGet        : Longint;
  28.     ErrorResult       : Integer;
  29.     ErrorMessage      : String;
  30.     Base64Found       : Boolean;
  31.     TheBoundaryString : String;
  32.     TheInputFileName : String;
  33.     TheOutputFileName : String;
  34.     TheInputTextFile : TextFile;
  35.     TheOutputBinaryFile : File of Byte;
  36.     constructor Create( AOwner : TComponent ); override;
  37.     function IsBoundaryToken( TheLine : String ) : String;
  38.     function IsDecodeName( TheLine : String ) : String;
  39.     function IsBase64( TheLine : String ) : Boolean;
  40.     function IsBoundary( TheLine : String ) : Boolean;
  41.     function DecodeMIMEFile : Boolean;
  42.     function OpenDecodeInputFile : Boolean;
  43.     function OpenDecodeOutputFile : Boolean;
  44.     function CloseDecodeFiles : Boolean;
  45.     procedure MIMEError( ECode : Integer; EMsg : String );
  46.     procedure MIMEUpdate( BSF , BT : LongInt );
  47.     function GetQuotedString( TheInputString : String ) : String;
  48.     function ConvertBase64Character( Current_Character : Char ) : SmallInt;
  49.     procedure InitializeMIMEDecode;
  50.     function GetTextFileSize( TheName : String ) : Longint;
  51.     function MIMEDecode( TheString : String ) : Boolean;
  52.     function AddBinaryValueToStream( BinaryValue : SmallInt ) : Boolean;
  53.     property OnMIMEErrorOccurred : TMIMEErrorEvent read FOnMIMEErrorOccurred
  54.      write FOnMIMEErrorOccurred;
  55.     property OnMIMEUpdateOccurred : TMIMEUpdateEvent read FOnMIMEUpdateOccurred
  56.      write FOnMIMEUpdateOccurred;
  57.   end;
  58.   { Component To Hold POP3/SMTP handling capabilities }
  59.   TPOP3SMTPComponent = class( TWinControl )
  60.   public
  61.     POP3CommandInProgress ,
  62.     SMTPCommandInProgress ,
  63.     Connection_Established : Boolean;
  64.     Socket1 : TCCSocket;
  65.     constructor Create( AOwner : TComponent ); override;
  66.     destructor Destroy; override;
  67.     function EstablishPOP3Connection( PCRPointer : PConnectionsRecord ) : Boolean;
  68.     function EstablishSMTPConnection( PCRPointer : PConnectionsRecord ) : Boolean;
  69.     function POP3Disconnect : Boolean;
  70.     function SMTPDisconnect : Boolean;
  71.     function DoCStyleFormat(       TheText      : string;
  72.                              const TheArguments : array of const ) : String;
  73.     procedure UpdateGauge( BytesFinished , TotalToHandle : longint );
  74.     procedure AddProgressText( WhatText : String );
  75.     procedure ShowProgressText( WhatText : String );
  76.     procedure ShowProgressErrorText( WhatText : String );
  77.     function GetPOP3ServerResponse( var ResponseString : String ) : integer;
  78.     function GetSMTPServerResponse( var ResponseString : String ) : integer;
  79.     procedure SetRecipient( WhichMemo : TMemo; WhatName : String );
  80.     procedure SetCarbonCopy( WhichMemo : TMemo; WhatName : String );
  81.     procedure POP3SMTPSocketsErrorOccurred( Sender     : TObject;
  82.                                      ErrorCode  : Integer;
  83.                                      TheMessage : String   );
  84.     function PerformPOP3Command(
  85.                     TheCommand   : string;
  86.               const TheArguments : array of const ) : Integer;
  87.     function PerformSMTPCommand(
  88.                     TheCommand   : string;
  89.               const TheArguments : array of const ) : Integer;
  90.     function PerformPOP3ExtendedCommand(
  91.                     TheCommand   : string;
  92.               const TheArguments : array of const ) : Integer;
  93.     function PerformSMTPExtendedCommand(
  94.                     TheCommand   : string;
  95.               const TheArguments : array of const ) : Integer;
  96.     function GetPOP3ServerExtendedResponse( ResponseString : PChar ) : integer;
  97.     function GetSMTPServerExtendedResponse( ResponseString : PChar ) : integer;
  98.     function GetNextSDItem(     WorkingString : String;
  99.                             var TheIndex      : Integer ) : String;
  100.     procedure PurgeTrashedMessageListings( TheEMBRecord : PEMailMailBoxRecord );
  101.     procedure TrashMessage( TheEMMRecord : PEMailMessageRecord );
  102.     procedure TrashAllMarkedMessages( TheLB       : TListBox;
  103.                                       TheMBRecord : PEMailMailboxRecord );
  104.     procedure ParseMailListing(     TheListing : String;
  105.                                 var TotalMessages : Longint;
  106.                                 var MessageBytes : Longint);
  107.     function CheckAllNewMail( var TotalBytes : Longint ) : Integer;
  108.     procedure SetMailHeaders( TheMemo      : TMemo;
  109.                              TheEMCRecord : PConnectionsRecord );
  110.     procedure InsertMIMETextHeader( TheMemo : TMemo );
  111.     procedure AddMIMEAttachment( TheMemo      : TMemo; TheFileToAdd : String );
  112.     procedure NewMIMEMessage( TheMemo      : TMemo; TheNewFile : String;
  113.                                TheEMCRecord : PConnectionsRecord );
  114.     procedure SetReplyMailHeaders( TheMemo         : TMemo ;
  115.                                   TheEMCRecord    : PConnectionsRecord;
  116.                                   TheEMBRecord    : PEmailMailBoxRecord;
  117.                                   MessageNumber   : Integer );
  118.     function GetMessageHeader( TheReturnList : TStringList ) : Longint;
  119.     function DownloadMessageListing( TheNumber   : Integer;
  120.                                      TheFileName : String;
  121.                                      TheHeaderSL : TStringList ) : Longint;
  122.     function DownloadAllMessageListings( TheEMBRecord : PEMailMailBoxRecord ) : Boolean;
  123.     function UploadMessageListing( TheEMMRecord : PEmailMessageRecord ) : Boolean;
  124.     function UploadAllMessageListings( PCRPointer : PConnectionsRecord;
  125.                                        TheEMBRecord : PEMailMailBoxRecord ) : Boolean;
  126.     function GetHeaderSubject( HList : TStringList ) : String;
  127.     function GetHeaderSender( HList : TStringList ) : String;
  128.     function GetHeaderRecipient( HList : TStringList ) : String;
  129.     function GetHeaderCarbons( HList : TStringList ) : String;
  130.     function GetHeaderBlindCarbons( HList : TStringList ) : String;
  131.     function GetRCPTHeaderRecipient( HList : TStringList ) : String;
  132.     function GetRCPTHeaderCarbons( HList : TStringList ) : String;
  133.     function GetRCPTHeaderBlindCarbons( HList : TStringList ) : String;
  134.     function GetHeaderDateTime( HList : TStringList ) : String;
  135.     procedure TransferMessage( SourceEMBRecord , TargetEMBRecord : PEMailMailBoxRecord;
  136.                               MessageNumber : Integer );
  137.     procedure ExtractHeaderInfoFromMemo( TheMemo      : TMemo;
  138.                                          TheEMMRecord : PEMailMessageRecord );
  139.     function LoginUser( PCRPointer : PConnectionsRecord ) : Boolean;
  140.     function SendPassword( PCRPointer : PConnectionsRecord ) : Boolean;
  141.     function SendHelo( PCRPointer : PConnectionsRecord ) : Boolean;
  142.     function SendMail( PCRPointer : PConnectionsRecord ) : Boolean;
  143.     function DeleteMailItem( TheNumber : Longint ) : Boolean;
  144.   end;
  145.  
  146. var
  147.   ThePOP3SMTPComponent  : TPOP3SMTPComponent; { Gee, which one is this? :) }
  148.   TheMIMEObject : TMIMECodingObject;
  149.  
  150. implementation
  151.  
  152. { Create constructor; sets update and error methods }
  153. constructor TMIMECodingObject.Create( AOwner : TComponent );
  154. begin
  155.   { Call inherited }
  156.   Inherited Create( AOwner );
  157.   { Setup two methods; can be overridden }
  158.   OnMIMEErrorOccurred := MIMEError;
  159.   OnMIMEUpdateOccurred := MIMEUpdate;
  160. end;
  161.  
  162. { This procedure resets the two decoding variables }
  163. procedure TMIMECodingObject.InitializeMIMEDecode;
  164. begin
  165.   The_Accumulator := 0;
  166.   Total_Bits_Shifted := 0;
  167.   BytesDone := 0;
  168. end;
  169.  
  170. { This is the generic error handler }
  171. procedure TMIMECodingObject.MIMEError( ECode : Integer; EMsg : String );
  172. begin
  173.   { Do generic MessageBox }
  174.   MessageDlg( 'A MIME error code ' + IntToStr( ECode ) +
  175.    ' has happend with Message ' + EMsg , mtError , [mbOK] , 0 );
  176. end;
  177.  
  178. { This is the generic update procedure }
  179. procedure TMIMECodingObject.MIMEUpdate( BSF , BT : LongInt );
  180. begin
  181.   CCInetCCForm.UpdateMIMEGauge( BSF , BT );
  182. end;
  183.  
  184. { This function takes an input string and returns any "" delimited text in it }
  185. function TMIMECodingObject.GetQuotedString( TheInputString : String ) : String;
  186. var HoldingString : String;  { Interim results holder }
  187.     PositionIndex : Integer; { " position holder      }
  188. begin
  189.   { Look for initial positon of double quote }
  190.   PositionIndex := Pos( '"' , TheInputString );
  191.   { If not found, then no quoted text; return empty string }
  192.   if PositionIndex = 0 then
  193.   begin
  194.     Result := '';
  195.     exit;
  196.   end;
  197.   { Otherwise get from just beyond " to end of string, allowing for unlimited }
  198.   { string sizes now in Delphi 2.0                                            }
  199.   HoldingString := Copy( TheInputString , PositionIndex + 1 ,
  200.    ( Length( TheInputString ) - PositionIndex ));
  201.   { Find ending " if any }
  202.   PositionIndex := Pos( '"' , HoldingString );
  203.   { If no ending " then assume all from first quote is result }
  204.   if PositionIndex = 0 then
  205.   begin
  206.     Result := HoldingString;
  207.     exit;
  208.   end;
  209.   { Otherwise get down to 1 before closing " }
  210.   HoldingString := Copy( HoldingString , 1 , PositionIndex - 1 );
  211.   { and return the ""-stripped string as desired }
  212.   Result := HoldingString;
  213. end;
  214.  
  215. { This function scans a line of text for the keyword 'boundary=' }
  216. function TMIMECodingObject.IsBoundaryToken( TheLine : String ) : String;
  217. begin
  218.   { Find out if it's a boundary token symbol }
  219.   if Pos( 'boundary=' , lowercase( TheLine )) <> 0 then
  220.   begin
  221.     { And grab the value }
  222.     Result := GetQuotedString( TheLine );
  223.   end
  224.   else
  225.   begin
  226.     { Else return empty string }
  227.     Result := '';
  228.   end;
  229. end;
  230.  
  231. { This function determines if the "name=" token is on a line and if so }
  232. { Returns the quoted file name as its result; otherwise it returns ''  }
  233. function TMIMECodingObject.IsDecodeName( TheLine : String ) : String;
  234. var PositionIndex : Integer; { Holds possible position of name= token }
  235.     HoldingString : String;  { Holds working string once token found  }
  236.     ResultString  : String;  { Holds name once stripped out of ""     }
  237. begin
  238.   { Find out if name= token in line }
  239.   PositionIndex := Pos( 'name=' , lowercase( TheLine ));
  240.   { If not reutrn the empty string }
  241.   if PositionIndex = 0 then
  242.   begin
  243.     Result := '';
  244.   end
  245.   else
  246.   begin
  247.     { Otherwise strip out stuff before token }
  248.     HoldingString := Copy( TheLine , PositionIndex + 1 ,
  249.      ( Length( TheLine ) - PositionIndex ));
  250.     { And send rest through stripquotes to get filename }
  251.     ResultString := GetQuotedString( HoldingString );
  252.     { Send it back; if malformed will be '' }
  253.     Result := ResultString;
  254.   end;
  255. end;
  256.  
  257. { This function returns true if the Base64 token is found, otherwise false }
  258. function TMIMECodingObject.IsBase64( TheLine : String ) : Boolean;
  259. begin
  260.   { if substring found assume valid token and return true else return false }
  261.   if Pos( 'base64' , lowercase( TheLine )) > 0 then Result := true
  262.    else Result := false;
  263. end;
  264.  
  265. { This funcion assumes the boundary string has been found; once it's known }
  266. { this function tells whether a line contains it.                          }
  267. function TMIMECodingObject.IsBoundary( TheLine : String ) : Boolean;
  268. begin
  269.   { A valid substring hit means true otherwise false }
  270.   if Pos( TheBoundaryString , TheLine ) <> 0 then Result := true else
  271.    Result := false;
  272. end;
  273.  
  274. { This is a clever function to get the total bytes of a text file }
  275. function TMIMECodingObject.GetTextFileSize( TheName : String ) : Longint;
  276. var TheSR : TSearchRec; { Used for trick }
  277. begin
  278.   { This allows getting the data }
  279.   FindFirst( TheName , faAnyFile , TheSR );
  280.   { And this is the info }
  281.   Result := TheSR.Size;
  282.   { Needed for win32 }
  283.   {FindClose( TheSR )};
  284. end;
  285.  
  286. { This function uses Try..Except loops to check for valid file openings }
  287. function TMIMECodingObject.OpenDecodeInputFile : Boolean;
  288. begin
  289.   { Use a try..except loop to catch IOErrors }
  290.   try
  291.     { assign the text input file to the input filename }
  292.     AssignFile( TheInputTextFile , TheInputFileName );
  293.     { do a reset }
  294.     Reset( TheInputTextFile );
  295.     { Get total bytes of a text file! }
  296.     BytesToGet := GetTextFileSize( TheInputFileName );
  297.   except
  298.     { Set error information on an input/output failure }
  299.     On E:EInOutError do
  300.     begin
  301.       { Get error message from exception object }
  302.       ErrorResult := -E.ErrorCode;
  303.       { Get filename and error message from exception object }
  304.       ErrorMessage := 'Unable to open Input File ' + TheInputFileName +
  305.        ' Due to ' + E.Message;
  306.       { if assigned error event then call it with info }
  307.       if Assigned( FOnMIMEErrorOccurred ) then
  308.        OnMIMEErrorOccurred( ErrorResult , ErrorMessage );
  309.       { return false on an error }
  310.       Result := false;
  311.       exit;
  312.     end;
  313.   end;
  314.   { Return true on no error }
  315.   Result := true;
  316. end;
  317.  
  318. { This function uses Try..Except loops to check for valid file openings }
  319. function TMIMECodingObject.OpenDecodeOutputFile : Boolean;
  320. begin
  321.   { Use a try..except loop to catch IOErrors }
  322.   try
  323.     { assign the binary output file to the parsed output filename }
  324.     AssignFile( TheOutputBinaryFile , TheOutputFileName );
  325.     { do a rewrite }
  326.     ReWrite( TheOutputBinaryFile );
  327.   except
  328.     { Set error information on an input/output failure }
  329.     On E:EInOutError do
  330.     begin
  331.       { Get error message from exception object }
  332.       ErrorResult := -E.ErrorCode;
  333.       { Get filename and error message from exception object }
  334.       ErrorMessage := 'Unable to open Output File ' + TheOutputFileName +
  335.        ' Due to ' + E.Message;
  336.       { if assigned error event then call it with info }
  337.       if Assigned( FOnMIMEErrorOccurred ) then
  338.        OnMIMEErrorOccurred( ErrorResult , ErrorMessage );
  339.       { return false on an error }
  340.       Result := false;
  341.       exit;
  342.     end;
  343.   end;
  344.   { Return true on no error }
  345.   Result := true;
  346. end;
  347.  
  348. { This closes both files and signals any error }
  349. function TMIMECodingObject.CloseDecodeFiles : Boolean;
  350. begin
  351.   { Use try..except to catch errors }
  352.   try
  353.     { Do both closefiles }
  354.     CloseFile( TheInputTextFile );
  355.     CloseFile( TheOutputBinaryFile );
  356.   except
  357.     { Set error information on an input/output failure }
  358.     On E:EInOutError do
  359.     begin
  360.       { Get error message from exception object }
  361.       ErrorResult := -E.ErrorCode;
  362.       { Get filename and error message from exception object }
  363.       ErrorMessage := 'Unable to close file(s) ' + ' Due to ' + E.Message;
  364.       { if assigned error event then call it with info }
  365.       if Assigned( FOnMIMEErrorOccurred ) then
  366.        OnMIMEErrorOccurred( ErrorResult , ErrorMessage );
  367.       { return false on an error }
  368.       Result := false;
  369.       exit;
  370.     end;
  371.   end;
  372.   { No error sends true }
  373.   Result := true;
  374. end;
  375.  
  376. { This function assumes the input filename is set but it does the rest }
  377. function TMIMECodingObject.DecodeMIMEFile : Boolean;
  378. var Finished      : Boolean; { Loop control variable }
  379.     Completed     : Boolean; { Loop control variable }
  380.     WorkingString : String;  { Input holder          }
  381. begin
  382.   { clear boundary marker }
  383.   TheBoundaryString := '';
  384.   { Set failure default return value; specific error handling }
  385.   { will be done be individual functions via ErrorResult and  }
  386.   { HandleMIMEError.                                          }
  387.   Result := false;
  388.   { Try to open the input text file }
  389.   if not OpenDecodeInputFile then exit;
  390.   { Clear loop variable }
  391.   Finished := false;
  392.   { Run till either end of file or signal done }
  393.   while (( not Finished ) and ( not EOF( TheInputTextFile ))) do
  394.   begin
  395.     { Get a line }
  396.     Readln( TheInputTextFile , WorkingString );
  397.     { Do the process count }
  398.     BytesDone := BytesDone + Length( WorkingString );
  399.     { Find out if the boundary token }
  400.     TheBoundaryString := IsBoundaryToken( WorkingString );
  401.     { If found then set exit variable }
  402.     if TheBoundaryString <> '' then Finished := true;
  403.   end;
  404.   { if no boundary marker found then go bye bye }
  405.   if TheBoundaryString = '' then
  406.   begin
  407.     { Set error message }
  408.     ErrorResult := -101;
  409.     { Get filename and error message from exception object }
  410.     ErrorMessage := 'No Boundary Token Found!';
  411.     { if assigned error event then call it with info }
  412.     if Assigned( FOnMIMEErrorOccurred ) then
  413.      OnMIMEErrorOccurred( ErrorResult , ErrorMessage );
  414.     exit;
  415.   end;
  416.   { Clear control variables }
  417.   Finished := false;
  418.   Base64Found := false;
  419.   TheOutputFileName := '';
  420.   { run loop to get name and confirm base64 encoding }
  421.   while (( not Finished ) and ( not EOF( TheInputTextFile ))) do
  422.   begin
  423.     { This outer loop grabs lines of text; does multiple boundaries }
  424.     Readln( TheInputTextFile , WorkingString );
  425.     { Do the process count }
  426.     BytesDone := BytesDone + Length( WorkingString );
  427.     { if hit a boundary then look for the base64 stuff }
  428.     if IsBoundary( WorkingString ) then
  429.     begin
  430.       { Set loop control }
  431.       Completed := false;
  432.       { run until run out of file or hit blank line }
  433.       while (( not Completed ) and ( not EOF( TheInputTextfile ))) do
  434.       begin
  435.         { Get line }
  436.         Readln( TheInputTextFile , WorkingString );
  437.         { Do the process count }
  438.         BytesDone := BytesDone + Length( WorkingString );
  439.         { if a blank then go bye bye }
  440.         if WorkingString = '' then
  441.         begin
  442.           Completed := true;
  443.         end
  444.         else
  445.         begin
  446.           { Get both possible output name and base64 OK }
  447.           if TheOutputFileName = '' then
  448.            TheOutputFileName := IsDecodeName( WorkingString );
  449.           if not Base64Found then
  450.            Base64Found := IsBase64( WorkingString );
  451.         end;
  452.       end;
  453.       { if found a blank line then check for valid base64 file }
  454.       if Completed then
  455.       begin
  456.         { If got an output filename and found b64 then set finished }
  457.         if (( TheOutputFileName <> '' ) and Base64Found ) then
  458.          Finished := true;
  459.       end;
  460.     end;
  461.   end;
  462.   { If never completed or output data not found then exit }
  463.   if not Finished then
  464.   begin
  465.     if TheOutputFileName = '' then
  466.     begin
  467.       { Set error message }
  468.       ErrorResult := -102;
  469.       { Get filename and error message from exception object }
  470.       ErrorMessage := 'No output filename found!';
  471.       { if assigned error event then call it with info }
  472.       if Assigned( FOnMIMEErrorOccurred ) then
  473.        OnMIMEErrorOccurred( ErrorResult , ErrorMessage );
  474.     end
  475.     else
  476.     begin
  477.       { Set error message }
  478.       ErrorResult := -103;
  479.       { Get filename and error message from exception object }
  480.       ErrorMessage := 'Not Base64 encoding!';
  481.       { if assigned error event then call it with info }
  482.       if Assigned( FOnMIMEErrorOccurred ) then
  483.        OnMIMEErrorOccurred( ErrorResult , ErrorMessage );
  484.     end;
  485.     exit;
  486.   end;
  487.   { Try to open the decode output file }
  488.   if not OpenDecodeOutputFile then exit;
  489.   { Set loop control variable }
  490.   Finished := false;
  491.   { Set up the decode variables }
  492.   InitializeMIMEDecode;
  493.   { run loop to get binary data }
  494.   while (( not Finished ) and ( not EOF( TheInputTextFile ))) do
  495.   begin
  496.     { Get an input line }
  497.     Readln( TheInputTextFile , WorkingString );
  498.     { Do the process count }
  499.     BytesDone := BytesDone + Length( WorkingString );
  500.     { If it's a boundary then don't process it otherwise do decode }
  501.     if not IsBoundary( WorkingString ) then
  502.     begin
  503.       { If decodes ok keep going else abort }
  504.       if not MIMEDecode( WorkingString ) then exit;
  505.       { Update status indicator }
  506.       if Assigned( OnMIMEUpdateOccurred ) then
  507.        OnMIMEUpdateOccurred( BytesDone , BytesToGet );
  508.     end
  509.     { End processing if a boundary found }
  510.     else Finished := true;
  511.   end;
  512.   { Clear status indicator }
  513.   if Assigned( OnMIMEUpdateOccurred ) then
  514.    OnMIMEUpdateOccurred( BytesToGet , BytesToGet );
  515.   { Close the files }
  516.   if not CloseDecodeFiles then exit;
  517.   { Return success }
  518.   Result := true;
  519. end;
  520.  
  521. { This function returns a binary number based on the ascii of the input char }
  522. function TMIMECodingObject.ConvertBase64Character( Current_Character : Char ) :
  523.  SmallInt;
  524. begin
  525.    { Decode ordinals of uppercase characters 0 - 25 }
  526.    if (( Current_Character >= 'A' ) and
  527.        ( Current_Character <= 'Z' )) then
  528.    begin
  529.      result :=
  530.       SmallInt( Ord( Current_Character ) - Ord( 'A' ));
  531.      exit;
  532.    end;
  533.    { Decode ordinals of lowercase characters 26 - 51 }
  534.    if (( Current_Character >= 'a') and
  535.        ( Current_Character <= 'z')) then
  536.    begin
  537.      result := 26 +
  538.        SmallInt( Ord( Current_Character ) - Ord( 'a' ));
  539.      exit;
  540.    end;
  541.    { Decode ordinals of numbers 52 - 61 }
  542.    if (( Current_Character >= '0') and
  543.        ( Current_Character <= '9' )) then
  544.    begin
  545.      result := 52 +
  546.        SmallInt( Ord( Current_Character ) - Ord( '0' ));
  547.      exit;
  548.    end;
  549.    { Decode + as 62 }
  550.    if ( Current_Character = '+' ) then
  551.    begin
  552.      result := 62;
  553.      exit;
  554.    end;
  555.    { Decode / as 63 }
  556.    if ( Current_Character = '/' ) then
  557.    begin
  558.      result := 63;
  559.      exit;
  560.    end;
  561.    { Signal padding character = by -2 }
  562.    if ( Current_Character = '=' ) then
  563.    begin
  564.      result := -2;
  565.      exit;
  566.    end;
  567.    { Signal invalid character by -1 }
  568.    result := -1;
  569. end;
  570.  
  571. { This function does bit magic on the current data state and when appropriate }
  572. { writes a byte to the output file.                                           }
  573. function TMIMECodingObject.AddBinaryValueToStream( BinaryValue : SmallInt ) :
  574.  Boolean;
  575. var WorkingValue : SmallInt; { Used to store bit conversion }
  576.     OutputValue  : Byte;     { Used to store output byte    }
  577. begin
  578.   { Assume success; only error will be file write failure }
  579.   Result := true;
  580.   { Shift over six bits of the accumulator }
  581.   The_Accumulator := The_Accumulator SHL 6;
  582.   { Add the shift to the counter }
  583.   Total_Bits_Shifted := Total_Bits_Shifted + 6;
  584.   { OR in the acquired bits }
  585.   { first char =  6 bits }
  586.   { 2nd   char = 12 bits; moved back to 4 }
  587.   { 3rd   char = 10 bits; moved back to 2 }
  588.   { 4th   char =  8 bits; moved back to 0 }
  589.   The_Accumulator := ( The_Accumulator or BinaryValue );
  590.   { If have at least one valid output byte }
  591.   if  Total_Bits_Shifted >= 8 then
  592.   begin
  593.     { Reduce remaining bits by 8 }
  594.     Total_Bits_Shifted := Total_Bits_Shifted - 8;
  595.     { Grab last full 8 bits in the accumulator }
  596.     { note that continual shifting clears it   }
  597.     WorkingValue := The_Accumulator SHR Total_Bits_Shifted;
  598.     { Mask off the high byte of the smallint }
  599.     OutputValue := byte( WorkingValue and $00FF );
  600.     { Use try..except to write out the byte }
  601.     try
  602.       { Do a seek for safety }
  603.       Seek( TheOutputBinaryFile , FileSize( TheOutputBinaryFile ));
  604.       { write the data byte }
  605.       Write( TheOutputBinaryFile , OutputValue );
  606.     except
  607.       { Set error information on an input/output failure }
  608.       On E:EInOutError do
  609.       begin
  610.         { Get error message from exception object }
  611.         ErrorResult := -E.ErrorCode;
  612.         { Get filename and error message from exception object }
  613.         ErrorMessage := 'Unable to Write output byte Due to ' + E.Message;
  614.         { if assigned error event then call it with info }
  615.         if Assigned( FOnMIMEErrorOccurred ) then
  616.          OnMIMEErrorOccurred( ErrorResult , ErrorMessage );
  617.         { return false on an error }
  618.         Result := false;
  619.         exit;
  620.       end;
  621.     end;
  622.   end;
  623. end;
  624.  
  625. { This function does the dirty work of doing the MIME decoding }
  626. function TMIMECodingObject.MIMEDecode( TheString : String ) : Boolean;
  627. var Counter_1         : Integer;   { Loop counter }
  628.     Current_Character : Char;      { Decode char  }
  629.     Binary_Value      : SmallInt;  { Output value }
  630. begin
  631.   { Assume success }
  632.   Result := true;
  633.   { Ignore blank lines }
  634.   if TheString = '' then exit;
  635.   { Run along string }
  636.   for Counter_1 := 1 to Length( TheString ) do
  637.   begin
  638.     { get char to decode }
  639.     Current_Character := TheString[ Counter_1 ];
  640.     { convert char to binary via lookup function }
  641.     Binary_Value := ConvertBase64Character( Current_Character );
  642.     { if -2 hit = padding char; abort }
  643.     if Binary_Value = -2 then exit;
  644.     { if invalid char signal error }
  645.     if Binary_Value = -1 then
  646.     begin
  647.       { Set error message }
  648.       ErrorResult := -104;
  649.       { Get filename and error message from exception object }
  650.       ErrorMessage := 'Invalid Input Character!';
  651.       { if assigned error event then call it with info }
  652.       if Assigned( FOnMIMEErrorOccurred ) then
  653.        OnMIMEErrorOccurred( ErrorResult , ErrorMessage );
  654.       { signal error and exit }
  655.       Result := false;
  656.       exit;
  657.     end;
  658.     { try to send the binary value through the byte cruncher }
  659.     if not AddBinaryValueToStream( Binary_Value ) then
  660.     begin
  661.       { If failed return error since had disk write error }
  662.       Result := false;
  663.       exit;
  664.     end;
  665.   end;
  666. end;
  667.  
  668. procedure TPOP3SMTPComponent.TrashMessage( TheEMMRecord : PEMailMessageRecord );
  669. begin
  670.   TheEMMRecord^.MRMessageSender := 'DELETE ME';
  671. end;
  672.  
  673. procedure TPOP3SMTPComponent.TrashAllMarkedMessages( TheLB       : TListBox;
  674.                                                      TheMBRecord : PEMailMailboxRecord );
  675. var Counter_1 : Integer;
  676.     WorkingList : TList;
  677. begin
  678.   WorkingList := TList( TheMBRecord^.MBLTag );
  679.   for Counter_1 := 0 to TheLB.Items.Count - 1 do
  680.   begin
  681.     if TheLB.Selected[ Counter_1 ] then
  682.     begin
  683.       TrashMessage( PEMailMessageRecord( WorkingList.Items[ Counter_1 ] ));
  684.     end;
  685.   end;
  686. end;
  687.  
  688. procedure TPOP3SMTPComponent.SetRecipient( WhichMemo : TMemo; WhatName : String );
  689. var Finished : Boolean;
  690.     Counter_1 ,
  691.     FoundLine   : Integer;
  692. begin
  693.   Finished := false;
  694.   Counter_1 := 0;
  695.   FoundLine := -1;
  696.   while not Finished do
  697.   begin
  698.     if Pos( 'TO:' , Uppercase( WhichMemo.Lines[ Counter_1 ] )) <> 0 then
  699.     begin
  700.       FoundLine := Counter_1;
  701.       Finished := true;
  702.     end
  703.     else Inc( Counter_1 );
  704.     if Counter_1 > WhichMemo.Lines.Count then Finished := true;
  705.   end;
  706.   if FoundLine = -1 then exit;
  707.   WhichMemo.Lines[ FoundLine ] := 'TO: ' + WhatName;
  708. end;
  709.  
  710. procedure TPOP3SMTPComponent.SetCarbonCopy( WhichMemo : TMemo; WhatName : String );
  711. var Finished : Boolean;
  712.     Counter_1 ,
  713.     FoundLine   : Integer;
  714. begin
  715.   Finished := false;
  716.   Counter_1 := 0;
  717.   FoundLine := -1;
  718.   while not Finished do
  719.   begin
  720.     if Pos( 'CC:' , Uppercase( WhichMemo.Lines[ Counter_1 ] )) <> 0 then
  721.     begin
  722.       FoundLine := Counter_1;
  723.       Finished := true;
  724.     end
  725.     else Inc( Counter_1 );
  726.     if Counter_1 > WhichMemo.Lines.Count then Finished := true;
  727.   end;
  728.   if FoundLine = -1 then exit;
  729.   WhichMemo.Lines[ FoundLine ] := 'CC: ' + WhatName;
  730. end;
  731.  
  732. { This function calls an extended response POP3SMTP command routine }
  733. function TPOP3SMTPComponent.PerformPOP3ExtendedCommand(
  734.                TheCommand   : string;
  735.          const TheArguments : array of const ) : Integer;
  736. var TheBuffer : string; { Text buffer }
  737. begin
  738.   { If command in progress send back -1 error }
  739.   if POP3CommandInProgress then
  740.   begin
  741.     Result := -1;
  742.     exit;
  743.   end;
  744.   { Set status variable }
  745.   POP3CommandInProgress := True;
  746.   { Set global error code }
  747.   GlobalErrorCode := 0;
  748.   { Format output string }
  749.   TheBuffer := Format( TheCommand , TheArguments );
  750.   { Preset failure code }
  751.   Result := TCPIP_STATUS_FATAL_ERROR;
  752.   { If invalid socket or no connection abort }
  753.   if ( Socket1.TheSocket = INVALID_SOCKET ) or not Connection_Established then
  754.    exit;
  755.   { Send the buffer plus EOL chars }
  756.   Socket1.StringData := TheBuffer + #13#10;
  757.   { if abort due to timeout or other error exit }
  758.   if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  759.   { Otherwise return preliminary code }
  760.   Result := TCPIP_STATUS_PRELIMINARY;
  761. end;
  762.  
  763. { This function calls an extended response POP3SMTP command routine }
  764. function TPOP3SMTPComponent.PerformSMTPExtendedCommand(
  765.                TheCommand   : string;
  766.          const TheArguments : array of const ) : Integer;
  767. var TheBuffer : string; { Text buffer }
  768. begin
  769.   { If command in progress send back -1 error }
  770.   if SMTPCommandInProgress then
  771.   begin
  772.     Result := -1;
  773.     exit;
  774.   end;
  775.   { Set status variable }
  776.   SMTPCommandInProgress := True;
  777.   { Set global error code }
  778.   GlobalErrorCode := 0;
  779.   { Format output string }
  780.   TheBuffer := Format( TheCommand , TheArguments );
  781.   { Preset failure code }
  782.   Result := TCPIP_STATUS_FATAL_ERROR;
  783.   { If invalid socket or no connection abort }
  784.   if ( Socket1.TheSocket = INVALID_SOCKET ) or not Connection_Established then
  785.    exit;
  786.   { Send the buffer plus EOL chars }
  787.   Socket1.StringData := TheBuffer + #13#10;
  788.   { if abort due to timeout or other error exit }
  789.   if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  790.   { Otherwise return preliminary code }
  791.   Result := TCPIP_STATUS_PRELIMINARY;
  792. end;
  793.  
  794. { This function gets an extended period-ended multiline response from the server }
  795. function TPOP3SMTPComponent.GetPOP3ServerExtendedResponse( ResponseString : PChar ) : integer;
  796. var
  797.   { Assume ResponseString already allocated as 0..513 }
  798.   { Pointer to the response string }
  799.   TheBuffer ,
  800.   BufferPointer : array[0..255] of char;
  801.   HolderBuffer : array[0..513] of char;
  802.   { Character to check for response code }
  803.   ResponseChar   : char;
  804.   { Pointers into returned string }
  805.   TheIndex ,
  806.   TheLength     : integer;
  807.   { Control variable }
  808.   LeftoversInPan ,
  809.   Finished      : Boolean;
  810.   BufferString : String;
  811. begin
  812.   { Preset fatal error }
  813.   Result := TCPIP_STATUS_FATAL_ERROR;
  814.   { Start loop control }
  815.   LeftoversInPan := false;
  816.   Finished := false;
  817.   StrCopy( HolderBuffer , '' );
  818.   repeat
  819.     { Do a peek }
  820.     BufferString := Socket1.PeekData;
  821.     { If timeout or other error exit }
  822.     if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  823.     { Find end of line character }
  824.     TheIndex := Pos( #10 , BufferString );
  825.     if TheIndex = 0 then
  826.     begin
  827.       TheIndex := Pos( #13 , BufferString );
  828.       if TheIndex = 0 then
  829.       begin
  830.         TheIndex := Pos( #0 , BufferString );
  831.         if TheIndex = 0 then
  832.         begin
  833.           TheIndex := Length( BufferString );
  834.           LeftoversInPan := True;
  835.           StrPCopy( TheBuffer , BufferString );
  836.           StrCat( HolderBuffer , TheBuffer );
  837.           LeftoversOnTable := false;
  838.         end;
  839.       end;
  840.     end;
  841.     { If an end of line then process the line }
  842.     if TheIndex > 0 then
  843.     begin
  844.       { Get length of string }
  845.       TheLength := TheIndex;
  846.       { Receive actual data }
  847.       Socket1.CCSockReceive( Socket1.TheSocket   ,
  848.                              @BufferPointer[ 0 ] ,
  849.                              TheLength              );
  850.       { Abort if timeout or error }
  851.       if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  852.       { Put in the length byte }
  853.       BufferPointer[ TheLength ] := Chr( 0 );
  854.       if LeftOversOnTable then
  855.       begin
  856.         LeftOversOnTable := false;
  857.         StrCopy( ResponseString , HolderBuffer );
  858.         StrCat( ResponseString , BufferPointer );
  859.       end
  860.       else
  861.       begin
  862.         if not LeftoversInPan then StrCopy( ResponseString , BufferPointer );
  863.       end;
  864.       if LeftoversInPan then
  865.       begin
  866.         LeftoversInPan := false;
  867.         LeftoversOnTable := true;
  868.       end
  869.       else
  870.       begin
  871.         ResponseChar := ResponseString[ 0 ];
  872.         if (( ResponseChar = '.' ) and ( StrLen( ResponseString ) <= 3 )) then
  873.         begin
  874.           ResponseString[ 0 ] := ' ';
  875.           Finished := true;
  876.           Result := TCPIP_STATUS_COMPLETED;
  877.         end
  878.         else
  879.         begin
  880.           if ResponseChar = '.' then ResponseString[ 0 ] := ' ';
  881.           Finished := true;
  882.           Result := TCPIP_STATUS_PRELIMINARY;
  883.         end;
  884.       end;
  885.     end;
  886.   until ( Finished and ( not LeftoversOnTable ));
  887.   StrLCopy( ResponseString , ResponseString , StrLen( ResponseString ) - 2 );
  888. end;
  889.  
  890. { This function gets an extended period-ended multiline response from the server }
  891. function TPOP3SMTPComponent.GetSMTPServerExtendedResponse( ResponseString : PChar ) : integer;
  892. var
  893.   { Assume ResponseString already allocated as 0..513 }
  894.   { Pointer to the response string }
  895.   TheBuffer ,
  896.   BufferPointer : array[0..255] of char;
  897.   HolderBuffer : array[0..513] of char;
  898.   { Character to check for response code }
  899.   ResponseChar   : char;
  900.   { Pointers into returned string }
  901.   TheIndex ,
  902.   TheLength     : integer;
  903.   { Control variable }
  904.   LeftoversInPan ,
  905.   Finished      : Boolean;
  906.   BufferString : String;
  907. begin
  908.   { Preset fatal error }
  909.   Result := TCPIP_STATUS_FATAL_ERROR;
  910.   { Start loop control }
  911.   LeftoversInPan := false;
  912.   Finished := false;
  913.   StrCopy( HolderBuffer , '' );
  914.   repeat
  915.     { Do a peek }
  916.     BufferString := Socket1.PeekData;
  917.     { If timeout or other error exit }
  918.     if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  919.     { Find end of line character }
  920.     TheIndex := Pos( #10 , BufferString );
  921.     if TheIndex = 0 then
  922.     begin
  923.       TheIndex := Pos( #13 , BufferString );
  924.       if TheIndex = 0 then
  925.       begin
  926.         TheIndex := Pos( #0 , BufferString );
  927.         if TheIndex = 0 then
  928.         begin
  929.           TheIndex := Length( BufferString );
  930.           LeftoversInPan := True;
  931.           StrPCopy( TheBuffer , BufferString );
  932.           StrCat( HolderBuffer , TheBuffer );
  933.           LeftoversOnTable := false;
  934.         end;
  935.       end;
  936.     end;
  937.     { If an end of line then process the line }
  938.     if TheIndex > 0 then
  939.     begin
  940.       { Get length of string }
  941.       TheLength := TheIndex;
  942.       { Receive actual data }
  943.       Socket1.CCSockReceive( Socket1.TheSocket   ,
  944.                              @BufferPointer[ 0 ] ,
  945.                              TheLength              );
  946.       { Abort if timeout or error }
  947.       if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  948.       { Put in the length byte }
  949.       BufferPointer[ TheLength ] := Chr( 0 );
  950.       if LeftOversOnTable then
  951.       begin
  952.         LeftOversOnTable := false;
  953.         StrCopy( ResponseString , HolderBuffer );
  954.         StrCat( ResponseString , BufferPointer );
  955.       end
  956.       else
  957.       begin
  958.         if not LeftoversInPan then StrCopy( ResponseString , BufferPointer );
  959.       end;
  960.       if LeftoversInPan then
  961.       begin
  962.         LeftoversInPan := false;
  963.         LeftoversOnTable := true;
  964.       end
  965.       else
  966.       begin
  967.         ResponseChar := ResponseString[ 0 ];
  968.         if (( ResponseChar = '.' ) and ( StrLen( ResponseString ) <= 3 )) then
  969.         begin
  970.           ResponseString [ 0 ] := ' ';
  971.           Finished := true;
  972.           Result := TCPIP_STATUS_COMPLETED;
  973.         end
  974.         else
  975.         begin
  976.           if ResponseChar = '.' then ResponseString[ 0 ] := ' ';
  977.           Finished := true;
  978.           Result := TCPIP_STATUS_PRELIMINARY;
  979.         end;
  980.       end;
  981.     end;
  982.   until ( Finished and ( not LeftoversOnTable ));
  983.   StrLCopy( ResponseString , ResponseString , StrLen( ResponseString ) - 2 );
  984. end;
  985.  
  986. { This function moves along a string from an index, getting the next }
  987. { string delimited item or last one on string.                       }
  988. function TPOP3SMTPComponent.GetNextSDItem(     WorkingString : String;
  989.                                        var TheIndex      : Integer ) : String;
  990. var HoldingString : String;
  991. begin
  992.   HoldingString := Copy( WorkingString , TheIndex + 1 , 255 );
  993.   TheIndex := Pos( ' ' , HoldingString );
  994.   if TheIndex = 0 then
  995.   begin
  996.     Result := HoldingString;
  997.   end
  998.   else
  999.   begin
  1000.     HoldingString := Copy( HoldingString , 1 , TheIndex - 1 );
  1001.     Result := HoldingString;
  1002.   end;
  1003. end;
  1004.  
  1005. { This function Inserts a MIME header into a memo for EMail usage }
  1006. procedure TPOP3SMTPComponent.InsertMIMETextHeader( TheMemo : TMemo );
  1007. var Counter_1 : Integer;
  1008.     Finished  : Boolean;
  1009. begin
  1010.   Counter_1 := 0;
  1011.   Finished := false;
  1012.   while not Finished do
  1013.   begin
  1014.     if TheMemo.Lines[ Counter_1 ] = '' then
  1015.     begin
  1016.       Finished := true;
  1017.     end
  1018.     else
  1019.     begin
  1020.       Inc( Counter_1 );
  1021.       if Counter_1 = TheMemo.Lines.Count then exit;
  1022.     end;
  1023.   end;
  1024.   TheMemo.Lines.Insert( Counter_1 - 1 , 'Mime-Version: 1.0' );
  1025.   TheMemo.Lines.Insert( Counter_1 , 'Content-Type: multipart/mixed; boundary="' +
  1026.    TheMIMEObject.TheBoundaryString + '"' );
  1027.   TheMemo.Lines.Insert( Counter_1 + 1 , '' );
  1028.   TheMemo.Lines.Insert( Counter_1 + 2 , '--' + TheMIMEObject.TheBoundaryString );
  1029.   TheMemo.Lines.Insert( Counter_1 + 3 , 'Content-Type: text/plain; charset="us-ascii"' );
  1030. end;
  1031.  
  1032. { this method adds a MIME file as an attachment to a message }
  1033. procedure TPOP3SMTPComponent.AddMIMEAttachment( TheMemo : TMemo;
  1034.  TheFileToAdd : String );
  1035. var TempMemo  : TMemo;
  1036.     Counter_1 : Integer;
  1037. begin
  1038.   InsertMIMETextHeader( TheMemo );
  1039.   TempMemo := TMemo.Create( self );
  1040.   TempMemo.parent := self;
  1041.   Tempmemo.Visible := false;
  1042.   TempMemo.Width := TheMemo.Width;
  1043.   TempMemo.Height := TheMemo.Height;
  1044.   TempMemo.Lines.LoadFromFile( TheFileToAdd );
  1045.   TheMemo.Lines.Add( '' );
  1046.   for Counter_1 := 0 to TempMemo.Lines.Count - 1 do
  1047.    TheMemo.Lines.Add( TempMemo.Lines[ Counter_1 ] );
  1048.   TempMemo.Free;
  1049.   TheMemo.Lines.Add( '--' + TheMIMEObject.TheBoundarystring );
  1050. end;
  1051.  
  1052. { This method creates a new message with a MIME attachment  }
  1053. procedure TPOP3SMTPComponent.NewMIMEMessage( TheMemo : TMemo;
  1054.  TheNewFile : String; TheEMCRecord : PConnectionsRecord  );
  1055. begin
  1056.   SetMailHeaders( TheMemo , TheEMCRecord );
  1057.   AddMimeAttachment( TheMemo , TheNewFile );
  1058. end;
  1059.  
  1060. { This method puts all the headers into the memo, getting the group name from gn }
  1061. procedure TPOP3SMTPComponent.SetMailHeaders( TheMemo      : TMemo;
  1062.                                             TheEMCRecord : PConnectionsRecord );
  1063. var DateString , TimeString : String;
  1064.     DateData , TimeData : Word;
  1065.     D1,D2,D3,D4 : Word;
  1066. begin
  1067.   DecodeTime( Time , D1 , D2 , D3 , D4 );
  1068.   TimeData := D1 + D2 + D3 + D4;
  1069.   DecodeDate( Date , D1 , D2 , D3 );
  1070.   DateData := D1 + D2 + D3;
  1071.   with TheEMCRecord^ do
  1072.   begin
  1073.     TheMemo.Clear;
  1074.     TheMemo.Lines.Add( 'To:');
  1075.     TheMemo.Lines.Add( 'From: ' + CStartDir );
  1076.     TheMemo.Lines.Add( 'CC:' );
  1077.     TheMemo.Lines.Add( 'BCC:' );
  1078.     TheMemo.Lines.Add( 'Subject:');
  1079.     TheMemo.Lines.Add( 'Message-ID: <' + IntToStr( DateData ) + IntToStr( TimeData ) +
  1080.      '@' + CIPAddress + '>' );
  1081.     TheMemo.Lines.Add( 'X-Mailer: CC Internet Command Center' );
  1082.     DateString := FormatDateTime( '"Date: "  ddd ' + '" " dd mmm yy', Date );
  1083.     TimeString := FormatDateTime( '" " hh:nn:ss' ,Time );
  1084.     TheMemo.Lines.Add( DateString  + TimeString + ' MDT' );
  1085.     TheMemo.Lines.Add( '' );
  1086.   end;
  1087. end;
  1088.  
  1089. { This function adds the text of an article to the current memo with > }
  1090. procedure TPOP3SMTPComponent.SetReplyMailHeaders(
  1091.           TheMemo         : TMemo ;
  1092.           TheEMCRecord    : PConnectionsRecord;
  1093.           TheEMBRecord    : PEmailMailBoxRecord;
  1094.           MessageNumber   : Integer );
  1095. var WorkingList     : TList;
  1096.     TheEMMRecord    : PEmailMessageRecord;
  1097.     Counter_1       : Integer;
  1098.     WorkingFileName : String;
  1099.     DateString ,
  1100.     TimeString      : String;
  1101.     DateData , TimeData : Word;
  1102.     D1,D2,D3,D4 : Word;
  1103. begin
  1104.   DecodeTime( Time , D1 , D2 , D3 , D4 );
  1105.   TimeData := D1 + D2 + D3 + D4;
  1106.   DecodeDate( Date , D1 , D2 , D3 );
  1107.   DateData := D1 + D2 + D3;
  1108.   WorkingList := TList( TheEMBRecord^.MBLTag );
  1109.   TheEMMRecord := PEmailMessageRecord( WorkingList.Items[ MessageNumber ] );
  1110.   WorkingFileName := TheEMMRecord^.MRFileName;
  1111.   WorkingFileName := MailPath + '\' + WorkingFileName;
  1112.   try
  1113.     TheMemo.Lines.LoadFromFile( WorkingFileName );
  1114.   except
  1115.     MessageDlg('Message File Too Big for Memo!',mtError,[mbOK],0);
  1116.   end;
  1117.   for Counter_1 := 0 to TheMemo.Lines.Count - 1 do
  1118.    TheMemo.Lines[ Counter_1 ] := '>' + TheMemo.Lines[ Counter_1 ];
  1119.   TheMemo.Lines.Insert( 0 , 'To:' + TheEMMRecord^.MRMessageSender );
  1120.   TheMemo.Lines.Insert( 1 , 'From:' + TheEMCRecord^.CStartDir );
  1121.   TheMemo.Lines.Insert( 2 , 'CC:' );
  1122.   TheMemo.Lines.Insert( 3 , 'BCC:' );
  1123.   TheMemo.Lines.Insert( 4 , 'Subject: Re: ' + TheEMMRecord^.MRMessageSubject );
  1124.   TheMemo.Lines.Insert( 5 , 'Message-ID: <' + IntToStr( DateData ) + IntToStr( TimeData ) +
  1125.    '@' + TheEMCRecord^.CIPAddress + '>' );
  1126.   TheMemo.Lines.Insert( 6 , 'X-Mailer: CC Internet Command Center' );
  1127.   DateString := FormatDateTime( '"Date: " ddd ' + '" "  dd mmm yy ', Date );
  1128.   TimeString := FormatDateTime( '" " hh:nn:ss' ,Time );
  1129.   TheMemo.Lines.Insert( 7 , DateString  + TimeString + ' MDT' );
  1130.   TheMemo.Lines.Insert( 8 , '' );
  1131. end;
  1132.  
  1133. { This method assumes logged into server; gets data via STAT command }
  1134. { returns total bytes in var'd param and total messages as result    }
  1135. function TPOP3SMTPComponent.CheckAllNewMail( var TotalBytes : Longint ) : Integer;
  1136. var TheReturnString : String;  { Internal string holder }
  1137.     TheResult       : Integer; { Internal int holder    }
  1138.     TheLResult      : Longint;
  1139. begin
  1140.   TheReturnString :=
  1141.    DoCStyleFormat( 'STAT' , [ nil ] );
  1142.   { Put result in progress and status line }
  1143.   AddProgressText( TheReturnString );
  1144.   ShowProgressText( TheReturnString );
  1145.   { Begin login sequence with user name }
  1146.   TheResult := PerformPOP3Command( 'STAT', [ nil ] );
  1147.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1148.   begin
  1149.     POP3CommandInProgress := false;
  1150.     Result := -1;
  1151.     exit;
  1152.   end;
  1153.   repeat
  1154.     TheResult := GetPOP3ServerResponse( TheReturnString );
  1155.     { Put result in progress and status line }
  1156.     AddProgressText( TheReturnString );
  1157.     ShowProgressText( TheReturnString + #13#10 );
  1158.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1159.   POP3CommandInProgress := false;
  1160.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  1161.   begin
  1162.     { Do clever C formatting trick }
  1163.     TheReturnString :=
  1164.      DoCStyleFormat( 'Mail Not Available!' , [ nil ] );
  1165.     { Put result in progress and status line }
  1166.     AddProgressText( TheReturnString );
  1167.     ShowProgressErrorText( TheReturnString );
  1168.     { Signal error }
  1169.     Result := -1;
  1170.     { leave }
  1171.     exit;
  1172.   end;
  1173.   ParseMailListing( TheReturnString , TheLResult , TotalBytes );
  1174.   Result := TheLResult;
  1175. end;
  1176.  
  1177. function TPOP3SMTPComponent.DeleteMailItem( TheNumber : Longint ) : Boolean;
  1178. var TheReturnString : String;  { Internal string holder }
  1179.     TheResult       : Integer; { Internal int holder    }
  1180. begin
  1181.   TheReturnString :=
  1182.    DoCStyleFormat( 'DELE %d' , [ TheNumber ] );
  1183.   { Put result in progress and status line }
  1184.   AddProgressText( TheReturnString );
  1185.   ShowProgressText( TheReturnString );
  1186.   { Begin login sequence with user name }
  1187.   TheResult := PerformPOP3Command( 'DELE %d', [ TheNumber ] );
  1188.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1189.   begin
  1190.     POP3CommandInProgress := false;
  1191.     Result := false;
  1192.     exit;
  1193.   end;
  1194.   repeat
  1195.     TheResult := GetPOP3ServerResponse( TheReturnString );
  1196.     { Put result in progress and status line }
  1197.     AddProgressText( TheReturnString );
  1198.     ShowProgressText( TheReturnString + #13#10 );
  1199.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1200.   POP3CommandInProgress := false;
  1201.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  1202.   begin
  1203.     { Do clever C formatting trick }
  1204.     TheReturnString :=
  1205.      DoCStyleFormat( 'Mail Not Available!' , [ nil ] );
  1206.     { Put result in progress and status line }
  1207.     AddProgressText( TheReturnString );
  1208.     ShowProgressErrorText( TheReturnString );
  1209.     { Signal error }
  1210.     Result := false;
  1211.     { leave }
  1212.     exit;
  1213.   end;
  1214.   Result := True;
  1215. end;
  1216.  
  1217. { This method splits up a listing and pulls out its component data }
  1218. procedure TPOP3SMTPComponent.ParseMailListing(     TheListing : String;
  1219.                                                var TotalMessages : Longint;
  1220.                                                var MessageBytes : Longint);
  1221. var HoldingString ,
  1222.     HoldingString2 : String;
  1223.     WorkingIndex  : Integer;
  1224. begin
  1225.   WorkingIndex := Pos( ' ' , TheListing );
  1226.   HoldingString := Copy( TheListing , WorkingIndex + 1 , 255 );
  1227.   WorkingIndex := Pos(  ' ' , HoldingString );
  1228.   HoldingString2 := Copy( HoldingString , 1 , WorkingIndex - 1 );
  1229.   TotalMessages := StrToInt( HoldingString2 );
  1230.   HoldingString := Copy( HoldingString , WorkingIndex + 1 , 255 );
  1231.   WorkingIndex := Pos(  ' ' , HoldingString );
  1232.   if WorkingIndex = 0 then WorkingIndex := 256;
  1233.   HoldingString2 := Copy( HoldingString , 1 , WorkingIndex - 1 );
  1234.   MessageBytes := StrToInt( HoldingString2 );
  1235. end;
  1236.  
  1237. { This method accumulates all the strings until '' as a messge header }
  1238. function TPOP3SMTPComponent.GetMessageHeader( TheReturnList : TStringList ) : Longint;
  1239. var TheReturnString : String;  { Internal string holder }
  1240.     TheResult       : Integer; { Internal int holder    }
  1241.     TheReturnPChar ,
  1242.     TheHoldingPChar : PChar;
  1243.     TotalGotten : Longint;
  1244. begin
  1245.   GetMem( TheReturnPChar , 514 );
  1246.   TheReturnList.Clear;
  1247.   TotalGotten := 0;
  1248.   repeat
  1249.     TheResult := GetPOP3ServerExtendedResponse( TheReturnPChar );
  1250.     if StrLen( TheReturnPChar ) < 3 then
  1251.     begin
  1252.      TheResult := TCPIP_STATUS_COMPLETED;
  1253.     end;
  1254.     TotalGotten := TotalGotten + StrLen( TheReturnPChar ) + 2;
  1255.     if StrLen( TheReturnPChar ) > 255 then
  1256.     begin
  1257.       Getmem( TheHoldingPChar , 255 );
  1258.       while StrLen( TheReturnPChar ) > 255 do
  1259.       begin
  1260.         StrCopy( TheHoldingPChar , '' );
  1261.         StrMove( TheHoldingPChar , TheReturnPChar , 255 );
  1262.         TheReturnPChar := TheReturnPChar + 256;
  1263.         TheReturnString := StrPas( TheHoldingPChar );
  1264.         TheReturnList.Add( TheReturnString );
  1265.       end;
  1266.       StrCopy( TheHoldingPChar , '' );
  1267.       StrMove( TheHoldingPChar , TheReturnPChar , StrLen( TheReturnPChar ));
  1268.       TheReturnString := StrPas( TheHoldingPChar );
  1269.       TheReturnString := '\' + TheReturnString;
  1270.       TheReturnList.Add( TheReturnString );
  1271.       FreeMem( TheHoldingPChar , 255 );
  1272.     end
  1273.     else
  1274.     begin
  1275.       TheReturnString := StrPas( TheReturnPChar );
  1276.       TheReturnList.Add( TheReturnString );
  1277.     end;
  1278.   until (( GlobalAbortedFlag ) or ( TheResult = TCPIP_STATUS_COMPLETED ));
  1279.   FreeMem( TheReturnPChar , 514 );
  1280.   Result := TotalGotten;
  1281. end;
  1282.  
  1283. { This method parses a header stringlist and obtains the subject line }
  1284. function TPOP3SMTPComponent.GetHeaderSubject( HList : TStringList ) : String;
  1285. var Counter_1     : Integer;
  1286.     Finished      : Boolean;
  1287.     WorkingIndex  : Integer;
  1288.     WorkingString : String;
  1289. begin
  1290.   Counter_1 := 0;
  1291.   Finished := false;
  1292.   WorkingString := '[No Subject]';
  1293.   while (( not Finished ) and ( Counter_1 <= HList.Count - 1 )) do
  1294.   begin
  1295.     WorkingIndex := Pos( 'SUBJECT:' , Uppercase( HList.Strings[ Counter_1 ] ));
  1296.     if WorkingIndex > 0 then
  1297.     begin
  1298.       WorkingString := Copy( HList.Strings[ Counter_1 ] , 9 , 255 );
  1299.       Finished := true;
  1300.     end
  1301.     else Inc( Counter_1 );
  1302.   end;
  1303.   Result := WorkingString;
  1304. end;
  1305.  
  1306. { This method parses a header stringlist and obtains the sender's ID }
  1307. function TPOP3SMTPComponent.GetHeaderSender( HList : TStringList ) : String;
  1308. var Counter_1     : Integer;
  1309.     Finished      : Boolean;
  1310.     WorkingIndex  : Integer;
  1311.     WorkingString : String;
  1312. begin
  1313.   Counter_1 := 0;
  1314.   Finished := false;
  1315.   WorkingString := '';
  1316.   while (( not Finished ) and ( Counter_1 <= HList.Count - 1 )) do
  1317.   begin
  1318.     WorkingIndex := Pos( 'FROM:' , Uppercase( HList.Strings[ Counter_1 ] ));
  1319.     if WorkingIndex > 0 then
  1320.     begin
  1321.       WorkingString := Copy( HList.Strings[ Counter_1 ] , 7 , 255 );
  1322.       Finished := true;
  1323.     end
  1324.     else Inc( Counter_1 );
  1325.   end;
  1326.   Result := WorkingString;
  1327. end;
  1328.  
  1329. { This method strips out the TO: field of a mail message header }
  1330. function TPOP3SMTPComponent.GetHeaderRecipient( HList : TStringList ) : String;
  1331. var Counter_1     : Integer;
  1332.     Finished      : Boolean;
  1333.     WorkingIndex  : Integer;
  1334.     WorkingString : String;
  1335. begin
  1336.   Counter_1 := 0;
  1337.   Finished := false;
  1338.   WorkingString := '';
  1339.   while (( not Finished ) and ( Counter_1 <= HList.Count - 1 )) do
  1340.   begin
  1341.     WorkingIndex := Pos( 'TO:' , Uppercase( HList.Strings[ Counter_1 ] ));
  1342.     if WorkingIndex > 0 then
  1343.     begin
  1344.       WorkingString := Copy( HList.Strings[ Counter_1 ] , 5 , 255 );
  1345.       Finished := true;
  1346.     end
  1347.     else Inc( Counter_1 );
  1348.   end;
  1349.   Result := WorkingString;
  1350. end;
  1351.  
  1352. { This method strips out the TO: field of a mail message header }
  1353. function TPOP3SMTPComponent.GetRCPTHeaderRecipient( HList : TStringList ) : String;
  1354. var Counter_1     : Integer;
  1355.     Finished      : Boolean;
  1356.     WorkingIndex  : Integer;
  1357.     WorkingString : String;
  1358. begin
  1359.   Counter_1 := 0;
  1360.   Finished := false;
  1361.   WorkingString := '';
  1362.   while (( not Finished ) and ( Counter_1 <= HList.Count - 1 )) do
  1363.   begin
  1364.     WorkingIndex := Pos( 'TO:' , Uppercase( HList.Strings[ Counter_1 ] ));
  1365.     if WorkingIndex > 0 then
  1366.     begin
  1367.       WorkingString := 'TO:<' + Copy( HList.Strings[ Counter_1 ] , 5 , 255 ) + '>';
  1368.       Finished := true;
  1369.     end
  1370.     else Inc( Counter_1 );
  1371.   end;
  1372.   Result := WorkingString;
  1373. end;
  1374.  
  1375. { This method strips out the CC: field of a mail message header }
  1376. function TPOP3SMTPComponent.GetHeaderCarbons( HList : TStringList ) : String;
  1377. var Counter_1     : Integer;
  1378.     Finished      : Boolean;
  1379.     WorkingIndex  : Integer;
  1380.     WorkingString : String;
  1381. begin
  1382.   Counter_1 := 0;
  1383.   Finished := false;
  1384.   WorkingString := '';
  1385.   while (( not Finished ) and ( Counter_1 <= HList.Count - 1 )) do
  1386.   begin
  1387.     WorkingIndex := Pos( 'CC:' , Uppercase( HList.Strings[ Counter_1 ] ));
  1388.     if WorkingIndex > 0 then
  1389.     begin
  1390.       WorkingString := Copy( HList.Strings[ Counter_1 ] , 5 , 255 );
  1391.       Finished := true;
  1392.     end
  1393.     else Inc( Counter_1 );
  1394.   end;
  1395.   Result := WorkingString;
  1396. end;
  1397.  
  1398. { This method strips out the CC: field of a mail message header }
  1399. function TPOP3SMTPComponent.GetRCPTHeaderCarbons( HList : TStringList ) : String;
  1400. var Counter_1     : Integer;
  1401.     Finished      : Boolean;
  1402.     WorkingIndex  : Integer;
  1403.     WorkingString : String;
  1404. begin
  1405.   Counter_1 := 0;
  1406.   Finished := false;
  1407.   WorkingString := '';
  1408.   while (( not Finished ) and ( Counter_1 <= HList.Count - 1 )) do
  1409.   begin
  1410.     WorkingIndex := Pos( 'CC:' , Uppercase( HList.Strings[ Counter_1 ] ));
  1411.     if WorkingIndex > 0 then
  1412.     begin
  1413.       WorkingString := 'CC:<' + Copy( HList.Strings[ Counter_1 ] , 5 , 255 ) + '>';
  1414.       Finished := true;
  1415.     end
  1416.     else Inc( Counter_1 );
  1417.   end;
  1418.   Result := WorkingString;
  1419. end;
  1420.  
  1421. { This method strips out the BCC: field of a mail message header }
  1422. function TPOP3SMTPComponent.GetHeaderBlindCarbons( HList : TStringList ) : String;
  1423. var Counter_1     : Integer;
  1424.     Finished      : Boolean;
  1425.     WorkingIndex  : Integer;
  1426.     WorkingString : String;
  1427. begin
  1428.   Counter_1 := 0;
  1429.   Finished := false;
  1430.   WorkingString := '';
  1431.   while (( not Finished ) and ( Counter_1 <= HList.Count - 1 )) do
  1432.   begin
  1433.     WorkingIndex := Pos( 'BCC:' , Uppercase( HList.Strings[ Counter_1 ] ));
  1434.     if WorkingIndex > 0 then
  1435.     begin
  1436.       WorkingString := Copy( HList.Strings[ Counter_1 ] , 6 , 255 );
  1437.       Finished := true;
  1438.     end
  1439.     else Inc( Counter_1 );
  1440.   end;
  1441.   Result := WorkingString;
  1442. end;
  1443.  
  1444. { This method strips out the BCC: field of a mail message header }
  1445. function TPOP3SMTPComponent.GetRCPTHeaderBlindCarbons( HList : TStringList ) : String;
  1446. var Counter_1     : Integer;
  1447.     Finished      : Boolean;
  1448.     WorkingIndex  : Integer;
  1449.     WorkingString : String;
  1450. begin
  1451.   Counter_1 := 0;
  1452.   Finished := false;
  1453.   WorkingString := '';
  1454.   while (( not Finished ) and ( Counter_1 <= HList.Count - 1 )) do
  1455.   begin
  1456.     WorkingIndex := Pos( 'BCC:' , Uppercase( HList.Strings[ Counter_1 ] ));
  1457.     if WorkingIndex > 0 then
  1458.     begin
  1459.       WorkingString := 'BCC:<' + Copy( HList.Strings[ Counter_1 ] , 6 , 255 ) + '>';
  1460.       Finished := true;
  1461.     end
  1462.     else Inc( Counter_1 );
  1463.   end;
  1464.   Result := WorkingString;
  1465. end;
  1466.  
  1467. { This method strips out the DATE: field of a mail message header }
  1468. function TPOP3SMTPComponent.GetHeaderDateTime( HList : TStringList ) : String;
  1469. var Counter_1     : Integer;
  1470.     Finished      : Boolean;
  1471.     WorkingIndex  : Integer;
  1472.     WorkingString : String;
  1473. begin
  1474.   Counter_1 := 0;
  1475.   Finished := false;
  1476.   WorkingString := '';
  1477.   while (( not Finished ) and ( Counter_1 <= HList.Count - 1 )) do
  1478.   begin
  1479.     WorkingIndex := Pos( 'DATE:' , Uppercase( HList.Strings[ Counter_1 ] ));
  1480.     if WorkingIndex > 0 then
  1481.     begin
  1482.       WorkingString := Copy( HList.Strings[ Counter_1 ] , 7 , 255 );
  1483.       Finished := true;
  1484.     end
  1485.     else Inc( Counter_1 );
  1486.   end;
  1487.   Result := WorkingString;
  1488. end;
  1489.  
  1490. { This method transfers a message from one mailbox to another }
  1491. procedure TPOP3SMTPComponent.TransferMessage( SourceEMBRecord ,
  1492.                                               TargetEMBRecord : PEMailMailBoxRecord;
  1493.                                               MessageNumber : Integer );
  1494. var  WorkingList1 , WorkingList2 : TList;
  1495.      TheEMMRecord : PEMailMessageRecord;
  1496. begin
  1497.   WorkingList1 := TList( SourceEMBRecord^.MBLTag );
  1498.   WorkingList2 := TList( TargetEMBRecord^.MBLTag );
  1499.   TheEMMRecord := PEMailMessageRecord( WorkingList1.Items[ MessageNumber ] );
  1500.   WorkingList2.Add( TheEMMRecord );
  1501.   SourceEMBRecord^.MBLTag := Longint( WorkingList1 );
  1502.   TargetEMBRecord^.MBLTag := Longint( WorkingList2 );
  1503. end;
  1504.  
  1505. { This function deletes all read/sent articles and associated files }
  1506. procedure TPOP3SMTPComponent.PurgeTrashedMessageListings( TheEMBRecord : PEMailMailBoxRecord );
  1507. var TheEMMRecord   : PEMailMessageRecord;
  1508.     Counter_1      : Integer;
  1509.     WorkingList    : TList;
  1510.     Finished       : Boolean;
  1511. begin
  1512.   { Do this for ease of coding }
  1513.   with TheEMBRecord^ do
  1514.   begin
  1515.     { Get the current TList of article headers }
  1516.     WorkingList := TList( MBLTag );
  1517.     { Run up to total new articles }
  1518.     for Counter_1 := 0 to WorkingList.Count - 1 do
  1519.     begin
  1520.       TheEMMRecord := PEMailMessageRecord( WorkingList.Items[ Counter_1 ] );
  1521.       if ( TheEMMRecord^.MRMessageSender = 'DELETE ME' ) then
  1522.       begin
  1523.         Dec( MBTotal );
  1524.         if not TheEMMRecord^.MRRead then if MBUnReadTotal > 0 then Dec( MBUnReadTotal );
  1525.         if not TheEMMRecord^.MRSent then if MBUnSentTotal > 0 then Dec( MBUnSentTotal );
  1526.         if FileExists( MailPath + '\' + TheEMMRecord^.MRFilename ) then
  1527.          {DeleteFile( MailPath + '\' + TheEMMRecord^.MRFileName )};
  1528.       end;
  1529.     end;
  1530.     Counter_1 := 0;
  1531.     Finished := False;
  1532.     if WorkingList.Count = 0 then Finished := true;
  1533.     while Not Finished do
  1534.     begin
  1535.       TheEMMRecord := PEMailMessageRecord( WorkingList.Items[ Counter_1 ] );
  1536.       if ( TheEMMRecord^.MRMessageSender = 'DELETE ME' ) then
  1537.       begin
  1538.         WorkingList.Delete( Counter_1 );
  1539.       end
  1540.       else Counter_1 := Counter_1 + 1;
  1541.       if Counter_1 > WorkingList.Count - 1 then Finished := true;
  1542.     end;
  1543.   end;
  1544. end;
  1545.  
  1546. { This method uses the ARTICLE command to obtain an article and put it in a  }
  1547. { preset/supplied file. It is designed to work by itself or inside DAALs     }
  1548. function TPOP3SMTPComponent.DownloadMessageListing( TheNumber   : Integer;
  1549.                                                     TheFileName : String;
  1550.                                                     TheHeaderSL : TStringList   ) : Longint;
  1551. var TheReturnString : String;  { Internal string holder }
  1552.     TheResult       : Integer; { Internal int holder    }
  1553.     TheReturnPChar ,
  1554.     TheHoldingPChar : PChar;
  1555.     TheMessageFile       : TextFile;
  1556.     Counter_1   : Integer;
  1557.     TotalGotten : Longint;
  1558. begin
  1559.   TheReturnString :=
  1560.    DoCStyleFormat( 'RETR %d' ,
  1561.     [ TheNumber ] );
  1562.   { Put result in progress and status line }
  1563.   AddProgressText( TheReturnString );
  1564.   ShowProgressText( TheReturnString );
  1565.   { Begin login sequence with user name }
  1566.   TheResult := PerformPOP3Command( 'RETR %d', [ TheNumber ] );
  1567.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1568.   begin
  1569.     POP3CommandInProgress := false;
  1570.     Result := 0;
  1571.     exit;
  1572.   end;
  1573.   repeat
  1574.     TheResult := GetPOP3ServerResponse( TheReturnString );
  1575.     { Put result in progress and status line }
  1576.     AddProgressText( TheReturnString );
  1577.     ShowProgressText( TheReturnString + #13#10 );
  1578.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1579.   POP3CommandInProgress := false;
  1580.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  1581.   begin
  1582.     { Do clever C formatting trick }
  1583.     TheReturnString :=
  1584.      DoCStyleFormat( 'Retrieve Message %d Failed!' ,
  1585.       [ TheNumber ] );
  1586.     { Put result in progress and status line }
  1587.     AddProgressText( TheReturnString );
  1588.     ShowProgressErrorText( TheReturnString );
  1589.     { Signal error }
  1590.     Result := 0;
  1591.     { leave }
  1592.     exit;
  1593.   end;
  1594.   GetMem( TheReturnPChar , 514 );
  1595.   try
  1596.     AssignFile( TheMessageFile , TheFileName );
  1597.     Rewrite( TheMessageFile );
  1598.   except
  1599.     MessageDlg( 'Unable to open Mail Message file ' + TheFileName + '!' ,
  1600.      mtError , [mbok],0 );
  1601.     Socket1.OutOfBand := 'ABOR'+#13#10;
  1602.     repeat
  1603.       TheResult := GetPOP3ServerResponse( TheReturnString );
  1604.       { Put result in progress and status line }
  1605.       AddProgressText( TheReturnString );
  1606.       ShowProgressText( TheReturnString  + #13#10 );
  1607.     until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1608.     result := 0;
  1609.     exit;
  1610.   end;
  1611.   TotalGotten := GetMessageHeader( TheHeaderSL );
  1612.   for Counter_1 := 0 to TheHeaderSL.Count - 1 do
  1613.    Writeln( TheMessageFile , TheHeaderSL.Strings[ Counter_1 ] );
  1614.   repeat
  1615.     TheResult := GetPOP3ServerExtendedResponse( TheReturnPChar );
  1616.     TotalGotten := TotalGotten + StrLen( TheReturnPChar ) + 2;
  1617.     if StrLen( TheReturnPChar ) > 255 then
  1618.     begin
  1619.       Getmem( TheHoldingPChar , 255 );
  1620.       while StrLen( TheReturnPChar ) > 255 do
  1621.       begin
  1622.         StrCopy( TheHoldingPChar , '' );
  1623.         StrMove( TheHoldingPChar , TheReturnPChar , 255 );
  1624.         TheReturnPChar := TheReturnPChar + 256;
  1625.         TheReturnString := StrPas( TheHoldingPChar );
  1626.         Writeln( TheMessageFile , TheReturnString );
  1627.       end;
  1628.       StrCopy( TheHoldingPChar , '' );
  1629.       StrMove( TheHoldingPChar , TheReturnPChar , StrLen( TheReturnPChar ));
  1630.       TheReturnString := StrPas( TheHoldingPChar );
  1631.       TheReturnString := '\' + TheReturnString;
  1632.       Writeln( TheMessageFile , TheReturnString );
  1633.       FreeMem( TheHoldingPChar , 255 );
  1634.     end
  1635.     else
  1636.     begin
  1637.       TheReturnString := StrPas( TheReturnPChar );
  1638.       Writeln( TheMessageFile , TheReturnString );
  1639.     end;
  1640.   until (( GlobalAbortedFlag ) or ( TheResult = TCPIP_STATUS_COMPLETED ));
  1641.   FreeMem( TheReturnPChar , 514 );
  1642.   CloseFile( TheMessageFile );
  1643.   Result := TotalGotten;
  1644. end;
  1645.  
  1646. { This method Gets all the Article Listings for a newsgroup which have not been  }
  1647. { Downloaded and gets them into text files. It displays Article count, # & bytes }
  1648. { in the status line during the process.                                         }
  1649. function TPOP3SMTPComponent.DownloadAllMessageListings(
  1650.   TheEMBRecord : PEMailMailBoxRecord ) : Boolean;
  1651. var WorkingList   : TList;
  1652.     TheEMMRecord  : PEMailMessageRecord;
  1653.     Counter_1 : Integer;
  1654.     WorkingID ,
  1655.     WorkingNumber : Integer;
  1656.     WorkingFileName : String;
  1657.     BytesToGet : Longint;
  1658.     TotalMessages : Integer;
  1659.     WorkingSL : TStringList;
  1660.     BytesGotten : Longint;
  1661. begin
  1662.   Result := true;
  1663.   TotalMessages := CheckAllNewMail( BytesToGet );
  1664.   if TotalMessages < 0 then exit;
  1665.   if TotalMessages = 0 then
  1666.   begin
  1667.     MessageDlg( 'No New Mail!' , mtInformation, [mbOK],0);
  1668.     exit;
  1669.   end;
  1670.   with TheEMBRecord^ do
  1671.   begin
  1672.     WorkingID := MBIDNumber;
  1673.     WorkingNumber := MBMaxMsgNumber;
  1674.     WorkingList := TList( MBLTag );
  1675.     WorkingSL := TStringList.Create;
  1676.     for Counter_1 := 1 to TotalMessages do
  1677.     begin
  1678.       New( TheEMMRecord );
  1679.       WorkingNumber := WorkingNumber + 1;
  1680.       with TheEMMRecord^ do
  1681.       begin
  1682.         WorkingFileName := 'EM' + IntToStr( WorkingNumber );
  1683.         if Length( WorkingFileName ) > 8 then WorkingFileName :=
  1684.          Copy( WorkingFileName , 1 , 8 );
  1685.         WorkingFileName := WorkingFileName + '.' +
  1686.          IntToStr( WorkingID );
  1687.         MRFileName := WorkingFileName;
  1688.         WorkingFileName := MailPath + '\' + WorkingFileName;
  1689.         BytesGotten := DownloadMessageListing( Counter_1 , WorkingFileName , WorkingSL );
  1690.         if EMRemoteDeletionVector = 2 then DeleteMailItem( Counter_1 );
  1691.         UpdateGauge( BytesGotten , BytesToGet );
  1692.         MRMailBoxName      := MBName;
  1693.         MRMessageSubject   := GetHeaderSubject( WorkingSL );
  1694.         MRMessageRecipient := GetHeaderRecipient( WorkingSL );
  1695.         MRMessageSender    := GetHeaderSender( WorkingSL );
  1696.         MRCarbonCopy       := GetHeaderCarbons( WorkingSL );
  1697.         MRBlindCarbonCopy  := GetHeaderBlindCarbons( WorkingSL );
  1698.         MRDateTime         := GetHeaderDateTime( WorkingSL );
  1699.         MRRead             := false;
  1700.         MRSent             := false;
  1701.         MRFileName         := ExtractFileName( WorkingFileName );
  1702.         WorkingList.Add( TheEMMRecord );
  1703.       end;
  1704.     end;
  1705.     UpdateGauge( BytesToGet , BytesToGet );
  1706.     MBLTag := Longint( WorkingList );
  1707.     MBMaxMsgNumber := WorkingNumber;
  1708.     MBTotal       := MBTotal + TotalMessages;
  1709.     MBUnReadTotal := MBUnReadTotal + TotalMessages;
  1710.     Result := true;
  1711.   end;
  1712. end;
  1713.  
  1714. { This method sends a message via RCPT and DATA commands (assumes HELO and }
  1715. { and MAIL already sent via EstablishSMTPConnection.)                      }
  1716. function TPOP3SMTPComponent.UploadMessageListing(
  1717.           TheEMMRecord : PEmailMessageRecord ): Boolean;
  1718. var WorkingString   : String;
  1719.     WorkingFile     : TextFile;
  1720.     TheReturnString : String;  { Internal string holder }
  1721.     TheResult       : Integer; { Internal int holder    }
  1722. begin
  1723.   with TheEMMRecord^ do
  1724.   begin
  1725.     MRSent := true;
  1726.     MRRead := true;
  1727.     WorkingString := MailPath + '\' + MRFileName;
  1728.     try
  1729.       AssignFile( WorkingFile , WorkingString );
  1730.       Reset( WorkingFile );
  1731.     except
  1732.       MessageDlg( 'Unable to Send due to open error on '
  1733.        + Workingstring + '!' , mtError , [mbok],0 );
  1734.       Result := false;
  1735.       exit;
  1736.     end;
  1737.     if MRMessageRecipient <> '' then
  1738.     begin
  1739.       TheReturnString :=
  1740.        DoCStyleFormat( 'RCPT %s' ,
  1741.         [ MRMessageRecipient ] );
  1742.       { Put result in progress and status line }
  1743.       AddProgressText( TheReturnString );
  1744.       ShowProgressText( TheReturnString );
  1745.       SMTPCommandInProgress := false;
  1746.       { Begin login sequence with user name }
  1747.       TheResult := PerformSMTPCommand( 'RCPT %s', [ MRMessageRecipient ] );
  1748.       if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1749.       begin
  1750.         SMTPCommandInProgress := false;
  1751.         Result := false;
  1752.         exit;
  1753.       end;
  1754.       repeat
  1755.         TheResult := GetSMTPServerResponse( TheReturnString );
  1756.         { Put result in progress and status line }
  1757.         AddProgressText( TheReturnString );
  1758.         ShowProgressText( TheReturnString + #13#10 );
  1759.       until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1760.     end;
  1761.     if MRCarbonCopy <> 'CC:<>' then
  1762.     begin
  1763.       TheReturnString :=
  1764.        DoCStyleFormat( 'RCPT %s' ,
  1765.         [ MRCarbonCopy ] );
  1766.       { Put result in progress and status line }
  1767.       AddProgressText( TheReturnString );
  1768.       ShowProgressText( TheReturnString );
  1769.       { Begin login sequence with user name }
  1770.       SMTPCommandInProgress := false;
  1771.       TheResult := PerformSMTPCommand( 'RCPT %s', [ MRCarbonCopy ] );
  1772.       if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1773.       begin
  1774.         SMTPCommandInProgress := false;
  1775.         Result := false;
  1776.         exit;
  1777.       end;
  1778.       repeat
  1779.         TheResult := GetSMTPServerResponse( TheReturnString );
  1780.         { Put result in progress and status line }
  1781.         AddProgressText( TheReturnString );
  1782.         ShowProgressText( TheReturnString + #13#10 );
  1783.       until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1784.     end;
  1785.     if MRBlindCarbonCopy <> 'BCC:<>' then
  1786.     begin
  1787.       TheReturnString :=
  1788.        DoCStyleFormat( 'RCPT %s' ,
  1789.         [ MRBlindCarbonCopy ] );
  1790.       { Put result in progress and status line }
  1791.       AddProgressText( TheReturnString );
  1792.       ShowProgressText( TheReturnString );
  1793.       { Begin login sequence with user name }
  1794.       SMTPCommandInProgress := false;
  1795.       TheResult := PerformSMTPCommand( 'RCPT %s' , [ MRBlindCarbonCopy ] );
  1796.       if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1797.       begin
  1798.         SMTPCommandInProgress := false;
  1799.         Result := false;
  1800.         exit;
  1801.       end;
  1802.       repeat
  1803.         TheResult := GetSMTPServerResponse( TheReturnString );
  1804.         { Put result in progress and status line }
  1805.         AddProgressText( TheReturnString );
  1806.         ShowProgressText( TheReturnString + #13#10 );
  1807.       until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1808.     end;
  1809.     TheReturnString :=
  1810.      DoCStyleFormat( 'DATA' ,
  1811.       [ nil ] );
  1812.     { Put result in progress and status line }
  1813.     AddProgressText( TheReturnString );
  1814.     ShowProgressText( TheReturnString );
  1815.     { Begin login sequence with user name }
  1816.     SMTPCommandInProgress := false;
  1817.     TheResult := PerformSMTPCommand( 'DATA' , [ nil ] );
  1818.     if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1819.     begin
  1820.       SMTPCommandInProgress := false;
  1821.       Result := false;
  1822.       exit;
  1823.     end;
  1824.     repeat
  1825.       TheResult := GetSMTPServerResponse( TheReturnString );
  1826.       { Put result in progress and status line }
  1827.       AddProgressText( TheReturnString );
  1828.       ShowProgressText( TheReturnString + #13#10 );
  1829.     until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1830.     repeat
  1831.       SMTPCommandInProgress := false;
  1832.       ReadLn( WorkingFile , WorkingString );
  1833.       if WorkingString[ 1 ] = '.' then WorkingString := '.' + WorkingString;
  1834.       TheResult := PerformSMTPCommand( WorkingString , [ nil ] );
  1835.       if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1836.       begin
  1837.         SMTPCommandInProgress := false;
  1838.         Result := false;
  1839.         exit;
  1840.       end;
  1841.     until EOF( WorkingFile );
  1842.     CloseFile( WorkingFile );
  1843.     SMTPCommandInProgress := false;
  1844.     TheResult := PerformSMTPCommand( '.' , [ nil ] );
  1845.     if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1846.     begin
  1847.       SMTPCommandInProgress := false;
  1848.       Result := false;
  1849.       exit;
  1850.     end;
  1851.     repeat
  1852.       TheResult := GetSMTPServerResponse( TheReturnString );
  1853.       { Put result in progress and status line }
  1854.       AddProgressText( TheReturnString );
  1855.       ShowProgressText( TheReturnString  + #13#10 );
  1856.     until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1857.     Result := true;
  1858.   end;
  1859. end;
  1860.  
  1861. procedure TPOP3SMTPComponent.ExtractHeaderInfoFromMemo(
  1862.            TheMemo : TMemo; TheEMMRecord : PEMailMessageRecord );
  1863. var Counter_1    : Integer;
  1864.     Finished     : Boolean;
  1865.     TheWorkingSL : TStringList;
  1866. begin
  1867.   Counter_1 := 0;
  1868.   Finished := false;
  1869.   TheWorkingSL := TStringList.Create;
  1870.   while not Finished do
  1871.   begin
  1872.     if TheMemo.Lines[ Counter_1 ] = '' then
  1873.     begin
  1874.       Finished := true;
  1875.     end
  1876.     else
  1877.     begin
  1878.       TheWorkingSL.Add( TheMemo.Lines[ Counter_1 ] );
  1879.       Inc( Counter_1 );
  1880.     end;
  1881.   end;
  1882.   with TheEMMRecord^ do
  1883.   begin
  1884.     MRMessageSubject   := GetHeaderSubject( TheWorkingSL );
  1885.     MRMessageRecipient := GetRCPTHeaderRecipient( TheWorkingSL );
  1886.     MRMessageSender    := 'CIUPKC158';
  1887.     MRCarbonCopy       := GetRCPTHeaderCarbons( TheWorkingSL );
  1888.     MRBlindCarbonCopy  := GetRCPTHeaderBlindCarbons( TheWorkingSL );
  1889.     MRDateTime         := GetHeaderDateTime( TheWorkingSL );
  1890.   end;
  1891.   TheWorkingSL.Free;
  1892. end;
  1893.  
  1894. { This method takes an entire Newsgroup and scans for SENDER = CIUPKC158 and }
  1895. { if that article has not been posted posts it. (Used by queue system.)      }
  1896. function TPOP3SMTPComponent.UploadAllMessageListings( PCRPointer : PConnectionsRecord;
  1897.           TheEMBRecord : PEMailMailBoxRecord ) : Boolean;
  1898. var WorkingList : TList;
  1899.     Counter_1   : Integer;
  1900.     WorkingEMMRecord : PEMailMessageRecord;
  1901.     TheReturnString  : String;
  1902. begin
  1903.   Result := true;
  1904.   with TheEMBRecord^ do
  1905.   begin
  1906.     WorkingList := TList( MBLTag );
  1907.     for Counter_1 := 0 to WorkingList.Count - 1 do
  1908.     begin
  1909.       WorkingEMMRecord :=
  1910.        PEMailMessageRecord( WorkingList.Items[ Counter_1 ] );
  1911.       with WorkingEMMRecord^ do
  1912.       begin
  1913.         if MRMessageSender = 'CIUPKC158' then
  1914.         begin
  1915.           if not MRSent then
  1916.           begin
  1917.             SMTPCommandInProgress := false;
  1918.             SendMail( PCRPointer );
  1919.             UploadMessageListing( WorkingEMMRecord );
  1920.             Dec( MBUnSentTotal );
  1921.           end;
  1922.         end;
  1923.       end;
  1924.     end;
  1925.     MBLTag := Longint( WorkingList );
  1926.   end;
  1927.   TheReturnString := 'Message(s) Uploaded!';
  1928.   AddProgressText( TheReturnString );
  1929.   ShowProgressText( TheReturnString + #13#10 );
  1930. end;
  1931.  
  1932. { This sends FTP progress text to the Inet form }
  1933. procedure TPOP3SMTPComponent.ShowProgressErrorText( WhatText : String );
  1934. begin
  1935.  CCInetCCForm.ShowProgressErrorText( WhatText );
  1936. end;
  1937.  
  1938. { This is a core function! It performs an FTP command and if no timeout }
  1939. { return a preliminary ok.                                              }
  1940. function TPOP3SMTPComponent.PerformPOP3Command(
  1941.                  TheCommand        : string;
  1942.            const TheArguments      : array of const ) : Integer;
  1943. var TheBuffer : string; { Text buffer }
  1944. begin
  1945.   { If command in progress send back -1 error }
  1946.   if POP3CommandInProgress then
  1947.   begin
  1948.     Result := -1;
  1949.     exit;
  1950.   end;
  1951.   { Set status variable }
  1952.   POP3CommandInProgress := True;
  1953.   { Set global error code }
  1954.   GlobalErrorCode := 0;
  1955.   { Format output string }
  1956.   TheBuffer := Format( TheCommand , TheArguments );
  1957.   { Preset failure code }
  1958.   Result := TCPIP_STATUS_FATAL_ERROR;
  1959.   { If invalid socket or no connection abort }
  1960.   if ( Socket1.TheSocket = INVALID_SOCKET ) or not Connection_Established then
  1961.    exit;
  1962.   { Send the buffer plus EOL chars }
  1963.   Socket1.StringData := TheBuffer + #13#10;
  1964.   { if abort due to timeout or other error exit }
  1965.   if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  1966.   { Otherwise return preliminary code }
  1967.   Result := TCPIP_STATUS_PRELIMINARY;
  1968. end;
  1969.  
  1970. { This is a core function! It performs an FTP command and if no timeout }
  1971. { return a preliminary ok.                                              }
  1972. function TPOP3SMTPComponent.PerformSMTPCommand(
  1973.                  TheCommand        : string;
  1974.            const TheArguments      : array of const ) : Integer;
  1975. var TheBuffer : string; { Text buffer }
  1976. begin
  1977.   { If command in progress send back -1 error }
  1978.   if SMTPCommandInProgress then
  1979.   begin
  1980.     Result := -1;
  1981.     exit;
  1982.   end;
  1983.   { Set status variable }
  1984.   SMTPCommandInProgress := True;
  1985.   { Set global error code }
  1986.   GlobalErrorCode := 0;
  1987.   { Format output string }
  1988.   TheBuffer := Format( TheCommand , TheArguments );
  1989.   { Preset failure code }
  1990.   Result := TCPIP_STATUS_FATAL_ERROR;
  1991.   { If invalid socket or no connection abort }
  1992.   if ( Socket1.TheSocket = INVALID_SOCKET ) or not Connection_Established then
  1993.    exit;
  1994.   { Send the buffer plus EOL chars }
  1995.   Socket1.StringData := TheBuffer + #13#10;
  1996.   { if abort due to timeout or other error exit }
  1997.   if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  1998.   { Otherwise return preliminary code }
  1999.   Result := TCPIP_STATUS_PRELIMINARY;
  2000. end;
  2001.  
  2002. { This function gets up to 255 chars of data plus a return code from FTP serv }
  2003. function TPOP3SMTPComponent.GetPOP3ServerResponse(
  2004.           var ResponseString : String ) : integer;
  2005. var
  2006.   { Buffer string for response line }
  2007.   TheBuffer     : string;
  2008.   { Pointer to the response string }
  2009.   BufferPointer : array[0..255] of char absolute TheBuffer;
  2010.   { Character to check for response code }
  2011.   ResponseChar   : char;
  2012.   { Pointers into returned string }
  2013.   TheIndex ,
  2014.   TheLength     : integer;
  2015.   { Control variable }
  2016.   LeftoversInPan ,
  2017.   Finished      : Boolean;
  2018. begin
  2019.   { Preset fatal error }
  2020.   Result := TCPIP_STATUS_FATAL_ERROR;
  2021.   { Start loop control }
  2022.   LeftoversInPan := false;
  2023.   Finished := false;
  2024.   repeat
  2025.     { Do a peek }
  2026.     TheBuffer := Socket1.PeekData;
  2027.     { If timeout or other error exit }
  2028.     if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  2029.     { Find end of line character }
  2030.     TheIndex := Pos( #10 , TheBuffer );
  2031.     if TheIndex = 0 then
  2032.     begin
  2033.       TheIndex := Pos( #13 , TheBuffer );
  2034.       if TheIndex = 0 then
  2035.       begin
  2036.         TheIndex := Pos( #0 , TheBuffer );
  2037.         if TheIndex = 0 then
  2038.         begin
  2039.           TheIndex := Length( TheBuffer );
  2040.           LeftoversInPan := True;
  2041.           LeftoverText := LeftoverText + TheBuffer;
  2042.           LeftoversOnTable := false;
  2043.         end;
  2044.       end;
  2045.     end;
  2046.     { If an end of line then process the line }
  2047.     if TheIndex > 0 then
  2048.     begin
  2049.       { Get length of string }
  2050.       TheLength := TheIndex;
  2051.       { Receive actual data }
  2052.       Socket1.CCSockReceive( Socket1.TheSocket   ,
  2053.                              @BufferPointer[ 1 ] ,
  2054.                              TheLength              );
  2055.       { Abort if timeout or error }
  2056.       if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  2057.       { Put in the length byte }
  2058.       BufferPointer[ 0 ] := Chr( TheLength );
  2059.       if LeftOversOnTable then
  2060.       begin
  2061.         LeftOversOnTable := false;
  2062.         ResponseString := LeftoverText + TheBuffer;
  2063.         TheBuffer := ResponseString;
  2064.         LeftoverText := '';
  2065.       end;
  2066.       if LeftoversInPan then
  2067.       begin
  2068.         LeftoversInPan := false;
  2069.         LeftoversOnTable := true;
  2070.       end;
  2071.       { Get first number character }
  2072.       ResponseChar := TheBuffer[ 1 ];
  2073.       { Get the value of the number from 1 to 5 }
  2074.       if (( ResponseChar = '+' ) or ( ResponseChar = '-' )) then
  2075.       begin
  2076.         Finished := true;
  2077.         if ResponseChar = '+' then Result := TCPIP_STATUS_COMPLETED
  2078.          else Result := TCPIP_STATUS_FATAL_ERROR;
  2079.       end;
  2080.     end
  2081.     else
  2082.     begin
  2083.     end;
  2084.   until ( Finished and ( not LeftoversOnTable ));
  2085.   { Return buffer as response string }
  2086.   ResponseString := TheBuffer;
  2087.   ResponseString := Copy( ResponseString , 1, Length( ResponseString ) - 2 );
  2088. end;
  2089.  
  2090. { This function gets up to 255 chars of data plus a return code from FTP serv }
  2091. function TPOP3SMTPComponent.GetSMTPServerResponse(
  2092.           var ResponseString : String ) : integer;
  2093. var
  2094.   { Buffer string for response line }
  2095.   TheBuffer     : string;
  2096.   { Pointer to the response string }
  2097.   BufferPointer : array[0..255] of char absolute TheBuffer;
  2098.   { Character to check for response code }
  2099.   ResponseChar   : char;
  2100.   { Pointers into returned string }
  2101.   TheIndex ,
  2102.   TheLength     : integer;
  2103.   { Control variable }
  2104.   LeftoversInPan ,
  2105.   Finished      : Boolean;
  2106. begin
  2107.   { Preset fatal error }
  2108.   Result := TCPIP_STATUS_FATAL_ERROR;
  2109.   { Start loop control }
  2110.   LeftoversInPan := false;
  2111.   Finished := false;
  2112.   repeat
  2113.     { Do a peek }
  2114.     TheBuffer := Socket1.PeekData;
  2115.     { If timeout or other error exit }
  2116.     if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  2117.     { Find end of line character }
  2118.     TheIndex := Pos( #10 , TheBuffer );
  2119.     if TheIndex = 0 then
  2120.     begin
  2121.       TheIndex := Pos( #13 , TheBuffer );
  2122.       if TheIndex = 0 then
  2123.       begin
  2124.         TheIndex := Pos( #0 , TheBuffer );
  2125.         if TheIndex = 0 then
  2126.         begin
  2127.           TheIndex := Length( TheBuffer );
  2128.           LeftoversInPan := True;
  2129.           LeftoverText := LeftoverText + TheBuffer;
  2130.           LeftoversOnTable := false;
  2131.         end;
  2132.       end;
  2133.     end;
  2134.     { If an end of line then process the line }
  2135.     if TheIndex > 0 then
  2136.     begin
  2137.       { Get length of string }
  2138.       TheLength := TheIndex;
  2139.       { Receive actual data }
  2140.       Socket1.CCSockReceive( Socket1.TheSocket   ,
  2141.                              @BufferPointer[ 1 ] ,
  2142.                              TheLength              );
  2143.       { Abort if timeout or error }
  2144.       if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  2145.       { Put in the length byte }
  2146.       BufferPointer[ 0 ] := Chr( TheLength );
  2147.       if LeftOversOnTable then
  2148.       begin
  2149.         LeftOversOnTable := false;
  2150.         ResponseString := LeftoverText + TheBuffer;
  2151.         TheBuffer := ResponseString;
  2152.         LeftoverText := '';
  2153.       end;
  2154.       if LeftoversInPan then
  2155.       begin
  2156.         LeftoversInPan := false;
  2157.         LeftoversOnTable := true;
  2158.       end;
  2159.       { Get first number character }
  2160.       ResponseChar := TheBuffer[ 1 ];
  2161.       { Get the value of the number from 1 to 5 }
  2162.       if (( ResponseChar >= '1' ) and ( ResponseChar <= '5' )) then
  2163.       begin
  2164.         if TheBuffer[ 4 ] = '-' then
  2165.         begin
  2166.           Finished := true;
  2167.           Result := TCPIP_STATUS_PRELIMINARY;
  2168.         end
  2169.         else
  2170.         begin
  2171.           Finished := true;
  2172.           Result := Ord( ResponseChar ) - 48;
  2173.         end;
  2174.       end;
  2175.     end
  2176.     else
  2177.     begin
  2178.     end;
  2179.   until ( Finished and ( not LeftoversOnTable ));
  2180.   { Return buffer as response string }
  2181.   ResponseString := TheBuffer;
  2182.   ResponseString := Copy( ResponseString , 1, Length( ResponseString ) - 2 );
  2183. end;
  2184.  
  2185.  
  2186. { Boilerplate error routine }
  2187. procedure TPOP3SMTPComponent.POP3SMTPSocketsErrorOccurred( Sender     : TObject;
  2188.                                                  ErrorCode  : Integer;
  2189.                                                  TheMessage : String   );
  2190. begin
  2191.   CCInetCCForm.SocketsErrorOccurred( Sender,ErrorCode,TheMessage );
  2192. end;
  2193.  
  2194. { This is the POP3SMTP components POP3 initial connection routine }
  2195. function TPOP3SMTPComponent.EstablishPOP3Connection(
  2196.           PCRPointer : PConnectionsRecord ) : Boolean;
  2197. var TheReturnString : String;  { Internal string holder }
  2198.     TheResult       : Integer; { Internal int holder    }
  2199. begin
  2200.   { Set default FTP Port value }
  2201.   Socket1.PortName := '110';
  2202.   { Get the ip address from the record }
  2203.   Socket1.IPAddressName := PCRPointer^.CIPAddress;
  2204.   { Set blocking mode }
  2205.   Socket1.AsynchMode := False;
  2206.   { Clear condition variables }
  2207.   GlobalErrorCode := 0;
  2208.   GlobalAbortedFlag := false;
  2209.   { Actually attempt to connect }
  2210.   Socket1.CCSockConnect;
  2211.   { Check if connected }
  2212.   if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 ) or
  2213.       ( Socket1.TheSocket = INVALID_SOCKET )) then
  2214.   begin { Didn't connect; signal error and abort }
  2215.     { Do clever C formatting trick }
  2216.     TheReturnString :=
  2217.      DoCStyleFormat( 'POP3 Host %s Connection Failed!' ,
  2218.       [ PCRPointer^.CIPAddress ] );
  2219.     { Put result in progress and status line }
  2220.     AddProgressText( TheReturnString );
  2221.     ShowProgressErrorText( TheReturnString );
  2222.     { Signal error }
  2223.     Result := False;
  2224.     { leave }
  2225.     exit;
  2226.   end
  2227.   else
  2228.   begin
  2229.     Connection_Established := true;
  2230.     { Signal successful connection }
  2231.     TheReturnString := DoCStyleFormat(
  2232.       'Connected on Local port: %s with IP: %s',
  2233.       [ Socket1.GetSocketPort( Socket1.TheSocket ),
  2234.         Socket1.GetSocketIPAddress( Socket1.TheSocket )]);
  2235.     { Put result in progress and status line }
  2236.     CCINetCCForm.AddProgressText( TheReturnString );
  2237.     CCINetCCForm.ShowProgressText( TheReturnString );
  2238.     TheReturnString := DoCStyleFormat(
  2239.      'Connected to Remote port: %s with IP: %s',
  2240.       [ Socket1.GetSocketPeerPort( Socket1.TheSocket ),
  2241.         Socket1.GetSocketPeerIPAddress( Socket1.TheSocket )]);
  2242.     { Put result in progress and status line }
  2243.     CCINetCCForm.AddProgressText( TheReturnString );
  2244.     CCINetCCForm.ShowProgressText( TheReturnString );
  2245.     TheReturnString := DoCStyleFormat( 'Successfully connected to %s',
  2246.      [ Socket1.IPAddressName ]);
  2247.     { Put result in progress and status line }
  2248.     CCINetCCForm.AddProgressText( TheReturnString );
  2249.     CCINetCCForm.ShowProgressText( TheReturnString );
  2250.     repeat
  2251.       TheResult := GetPOP3ServerResponse( TheReturnString );
  2252.       { Put result in progress and status line }
  2253.       AddProgressText( TheReturnString );
  2254.       ShowProgressText( TheReturnString );
  2255.     until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  2256.     if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  2257.     begin
  2258.       { Do clever C formatting trick }
  2259.       TheReturnString :=
  2260.        DoCStyleFormat( 'POP3 Host %s Connection Failed!' ,
  2261.         [ PCRPointer^.CIPAddress ] );
  2262.       { Put result in progress and status line }
  2263.       AddProgressText( TheReturnString );
  2264.       ShowProgressErrorText( TheReturnString );
  2265.       { Signal error }
  2266.       Result := False;
  2267.       { leave }
  2268.       exit;
  2269.     end
  2270.     else Result := true; { Signal no problem }
  2271.   end;
  2272. end;
  2273.  
  2274. { This is the POP3SMTP components SMTP initial connection routine }
  2275. function TPOP3SMTPComponent.EstablishSMTPConnection(
  2276.           PCRPointer : PConnectionsRecord ) : Boolean;
  2277. var TheReturnString : String;  { Internal string holder }
  2278.     TheResult       : Integer; { Internal int holder    }
  2279. begin
  2280.   { Set default FTP Port value }
  2281.   Socket1.PortName := '25';
  2282.   { Get the ip address from the record }
  2283.   Socket1.IPAddressName := PCRPointer^.CIPAddress;
  2284.   { Set blocking mode }
  2285.   Socket1.AsynchMode := False;
  2286.   { Clear condition variables }
  2287.   GlobalErrorCode := 0;
  2288.   GlobalAbortedFlag := false;
  2289.   { Actually attempt to connect }
  2290.   Socket1.CCSockConnect;
  2291.   { Check if connected }
  2292.   if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 ) or
  2293.       ( Socket1.TheSocket = INVALID_SOCKET )) then
  2294.   begin { Didn't connect; signal error and abort }
  2295.     { Do clever C formatting trick }
  2296.     TheReturnString :=
  2297.      DoCStyleFormat( 'SMTP Host %s Connection Failed!' ,
  2298.       [ PCRPointer^.CIPAddress ] );
  2299.     { Put result in progress and status line }
  2300.     AddProgressText( TheReturnString );
  2301.     ShowProgressErrorText( TheReturnString );
  2302.     { Signal error }
  2303.     Result := False;
  2304.     { leave }
  2305.     exit;
  2306.   end
  2307.   else
  2308.   begin
  2309.     Connection_Established := true;
  2310.     { Signal successful connection }
  2311.     TheReturnString := DoCStyleFormat(
  2312.       'Connected on Local port: %s with IP: %s',
  2313.       [ Socket1.GetSocketPort( Socket1.TheSocket ),
  2314.         Socket1.GetSocketIPAddress( Socket1.TheSocket )]);
  2315.     { Put result in progress and status line }
  2316.     CCINetCCForm.AddProgressText( TheReturnString );
  2317.     CCINetCCForm.ShowProgressText( TheReturnString );
  2318.     TheReturnString := DoCStyleFormat(
  2319.      'Connected to Remote port: %s with IP: %s',
  2320.       [ Socket1.GetSocketPeerPort( Socket1.TheSocket ),
  2321.         Socket1.GetSocketPeerIPAddress( Socket1.TheSocket )]);
  2322.     { Put result in progress and status line }
  2323.     CCINetCCForm.AddProgressText( TheReturnString );
  2324.     CCINetCCForm.ShowProgressText( TheReturnString );
  2325.     TheReturnString := DoCStyleFormat( 'Successfully connected to %s',
  2326.      [ Socket1.IPAddressName ]);
  2327.     { Put result in progress and status line }
  2328.     CCINetCCForm.AddProgressText( TheReturnString );
  2329.     CCINetCCForm.ShowProgressText( TheReturnString );
  2330.     repeat
  2331.       TheResult := GetSMTPServerResponse( TheReturnString );
  2332.       { Put result in progress and status line }
  2333.       AddProgressText( TheReturnString );
  2334.       ShowProgressText( TheReturnString + #13#10 );
  2335.     until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  2336.     if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  2337.     begin
  2338.       { Do clever C formatting trick }
  2339.       TheReturnString :=
  2340.        DoCStyleFormat( 'SMTP Host %s Connection Failed!' ,
  2341.         [ PCRPointer^.CIPAddress ] );
  2342.       { Put result in progress and status line }
  2343.       AddProgressText( TheReturnString );
  2344.       ShowProgressErrorText( TheReturnString );
  2345.       { Signal error }
  2346.       Result := False;
  2347.       { leave }
  2348.       exit;
  2349.     end
  2350.     else Result := true; { Signal no problem }
  2351.   end;
  2352. end;
  2353.  
  2354. { This sends FTP progress text to the Inet form }
  2355. procedure TPOP3SMTPComponent.AddProgressText( WhatText : String );
  2356. begin
  2357.   CCInetCCForm.AddProgressText( WhatText );
  2358. end;
  2359.  
  2360. { This sends FTP progress text to the Inet form }
  2361. procedure TPOP3SMTPComponent.ShowProgressText( WhatText : String );
  2362. begin
  2363.   CCInetCCForm.ShowProgressText( WhatText );
  2364. end;
  2365.  
  2366. { This is a clever c-style formatting trick }
  2367. function TPOP3SMTPComponent.DoCStyleFormat(
  2368.                 TheText      : string;
  2369.           const TheArguments : array of const ) : String;
  2370. begin
  2371.   Result := Format( TheText , TheArguments ) + #13#10;
  2372. end;
  2373.  
  2374. { This is the FTP components USER login routine }
  2375. function TPOP3SMTPComponent.LoginUser(
  2376.           PCRPointer : PConnectionsRecord ) : Boolean;
  2377. var TheReturnString : String;  { Internal string holder }
  2378.     TheResult       : Integer; { Internal int holder    }
  2379. begin
  2380.   TheReturnString :=
  2381.    DoCStyleFormat( 'USER %s' ,
  2382.     [ PCRPointer^.CUserName ] );
  2383.   { Put result in progress and status line }
  2384.   AddProgressText( TheReturnString );
  2385.   ShowProgressText( TheReturnString );
  2386.   { Begin login sequence with user name }
  2387.   TheResult := PerformPOP3Command( 'USER %s',
  2388.                                   [ PCRPointer^.CUserName ] );
  2389.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  2390.   begin
  2391.     POP3CommandInProgress := false;
  2392.     Result := false;
  2393.     exit;
  2394.   end;
  2395.   repeat
  2396.     TheResult := GetPOP3ServerResponse( TheReturnString );
  2397.     { Put result in progress and status line }
  2398.     AddProgressText( TheReturnString );
  2399.     ShowProgressText( TheReturnString + #13#10 );
  2400.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  2401.   POP3CommandInProgress := false;
  2402.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  2403.   begin
  2404.     { Do clever C formatting trick }
  2405.     TheReturnString :=
  2406.      DoCStyleFormat( 'POP3 Host %s Login Failed!' ,
  2407.       [ PCRPointer^.CIPAddress ] );
  2408.     { Put result in progress and status line }
  2409.     AddProgressText( TheReturnString );
  2410.     ShowProgressErrorText( TheReturnString );
  2411.     { Signal error }
  2412.     Result := False;
  2413.     { leave }
  2414.     exit;
  2415.   end
  2416.   else Result := true; { Signal no problem }
  2417. end;
  2418.  
  2419. { This is the FTP components USER login routine }
  2420. function TPOP3SMTPComponent.SendHelo(
  2421.           PCRPointer : PConnectionsRecord ) : Boolean;
  2422. var TheReturnString : String;  { Internal string holder }
  2423.     TheResult       : Integer; { Internal int holder    }
  2424. begin
  2425.   TheReturnString :=
  2426.    DoCStyleFormat( 'HELO %s' ,
  2427.     [ Socket1.GetSocketIPAddress( Socket1.TheSocket ) ] );
  2428.   { Put result in progress and status line }
  2429.   AddProgressText( TheReturnString );
  2430.   ShowProgressText( TheReturnString );
  2431.   { Begin login sequence with user name }
  2432.   TheResult := PerformSMTPCommand( 'HELO %s',
  2433.                 [ Socket1.GetSocketIPAddress( Socket1.TheSocket ) ] );
  2434.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  2435.   begin
  2436.     POP3CommandInProgress := false;
  2437.     Result := false;
  2438.     exit;
  2439.   end;
  2440.   repeat
  2441.     TheResult := GetSMTPServerResponse( TheReturnString );
  2442.     { Put result in progress and status line }
  2443.     AddProgressText( TheReturnString );
  2444.     ShowProgressText( TheReturnString + #13#10 );
  2445.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  2446.   SMTPCommandInProgress := false;
  2447.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  2448.   begin
  2449.     { Do clever C formatting trick }
  2450.     TheReturnString :=
  2451.      DoCStyleFormat( 'SMTP Host %s Login Failed!' ,
  2452.       [ PCRPointer^.CIPAddress ] );
  2453.     { Put result in progress and status line }
  2454.     AddProgressText( TheReturnString );
  2455.     ShowProgressErrorText( TheReturnString );
  2456.     { Signal error }
  2457.     Result := False;
  2458.     { leave }
  2459.     exit;
  2460.   end
  2461.   else Result := true; { Signal no problem }
  2462. end;
  2463.  
  2464. { This is the FTP components USER login routine }
  2465. function TPOP3SMTPComponent.SendMail(
  2466.           PCRPointer : PConnectionsRecord ) : Boolean;
  2467. var TheReturnString : String;  { Internal string holder }
  2468.     TheResult       : Integer; { Internal int holder    }
  2469. begin
  2470.   TheReturnString :=
  2471.    DoCStyleFormat( 'MAIL FROM:<%s>' ,
  2472.     [ PCRPointer^.CStartDir ] );
  2473.   { Put result in progress and status line }
  2474.   AddProgressText( TheReturnString );
  2475.   ShowProgressText( TheReturnString );
  2476.   { Begin login sequence with user name }
  2477.   TheResult := PerformSMTPCommand( 'MAIL FROM:<%s>',
  2478.                                   [ PCRPointer^.CStartDir ] );
  2479.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  2480.   begin
  2481.     SMTPCommandInProgress := false;
  2482.     Result := false;
  2483.     exit;
  2484.   end;
  2485.   repeat
  2486.     TheResult := GetSMTPServerResponse( TheReturnString );
  2487.     { Put result in progress and status line }
  2488.     AddProgressText( TheReturnString );
  2489.     ShowProgressText( TheReturnString + #13#10 );
  2490.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  2491.   SMTPCommandInProgress := false;
  2492.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  2493.   begin
  2494.     { Do clever C formatting trick }
  2495.     TheReturnString :=
  2496.      DoCStyleFormat( 'SMTP Host %s Login Failed!' ,
  2497.       [ PCRPointer^.CIPAddress ] );
  2498.     { Put result in progress and status line }
  2499.     AddProgressText( TheReturnString );
  2500.     ShowProgressErrorText( TheReturnString );
  2501.     { Signal error }
  2502.     Result := False;
  2503.     { leave }
  2504.     exit;
  2505.   end
  2506.   else Result := true; { Signal no problem }
  2507. end;
  2508.  
  2509. { This is the FTP components PASSWORD routine }
  2510. function TPOP3SMTPComponent.SendPassword(
  2511.           PCRPointer : PConnectionsRecord ) : Boolean;
  2512. var TheReturnString : String;  { Internal string holder }
  2513.     TheResult       : Integer; { Internal int holder    }
  2514. begin
  2515.   TheReturnString := 'PASS XXXXXX' + #13#10;
  2516.   { Put result in progress and status line }
  2517.   AddProgressText( TheReturnString );
  2518.   ShowProgressText( TheReturnString );
  2519.   { Send Password sequence }
  2520.   TheResult := PerformPOP3Command( 'PASS %s',
  2521.                                   [ PCRPointer^.CPassword ] );
  2522.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  2523.   begin
  2524.     Result := false;
  2525.     POP3CommandInProgress := false;
  2526.     exit;
  2527.   end;
  2528.   repeat
  2529.     TheResult := GetPOP3ServerResponse( TheReturnString );
  2530.     { Put result in progress and status line }
  2531.     AddProgressText( TheReturnString );
  2532.     ShowProgressText( TheReturnString + #13#10 );
  2533.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  2534.   POP3CommandInProgress := false;
  2535.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  2536.   begin
  2537.     { Do clever C formatting trick }
  2538.     TheReturnString :=
  2539.      DoCStyleFormat( 'POP3 Host %s Login Failed!' ,
  2540.       [ PCRPointer^.CIPAddress ] );
  2541.     { Put result in progress and status line }
  2542.     AddProgressText( TheReturnString );
  2543.     ShowProgressErrorText( TheReturnString );
  2544.     { Signal error }
  2545.     Result := False;
  2546.     { leave }
  2547.     exit;
  2548.   end
  2549.   else Result := true; { Signal no problem }
  2550. end;
  2551.  
  2552. { This is the FTP component constructor; it creates 2 sockets }
  2553. constructor TPOP3SMTPComponent.Create( AOwner : TComponent );
  2554. begin
  2555.   { do inherited create }
  2556.   inherited Create( AOwner );
  2557.   { Create sockets, put in their parents, and error procs }
  2558.   Socket1 := TCCSocket.Create( Self );
  2559.   Socket1.Parent := Self;
  2560.   Socket1.OnErrorOccurred := POP3SMTPSocketsErrorOccurred;
  2561.   { Set up booleans }
  2562.   Connection_Established := false;
  2563.   POP3CommandInProgress := false;
  2564.   SMTPCommandInProgress := false;
  2565. end;
  2566.  
  2567. { This is the FTP component destructor; it frees 2 sockets }
  2568. destructor TPOP3SMTPComponent.Destroy;
  2569. begin
  2570.   { Free the sockets }
  2571.   Socket1.Free;
  2572.   { and call inherited }
  2573.   inherited Destroy;
  2574. end;
  2575.  
  2576. { This is the POP3 components QUIT routine }
  2577. function TPOP3SMTPComponent.POP3Disconnect : Boolean;
  2578. var TheReturnString : String;  { Internal string holder }
  2579.     TheResult       : Integer; { Internal int holder    }
  2580. begin
  2581.   TheReturnString :=
  2582.    DoCStyleFormat( 'QUIT' ,
  2583.     [ nil ] );
  2584.   { Put result in progress and status line }
  2585.   AddProgressText( TheReturnString );
  2586.   ShowProgressText( TheReturnString );
  2587.   { Begin login sequence with user name }
  2588.   PerformPOP3Command( 'QUIT', [ nil ] );
  2589.   repeat
  2590.     TheResult := GetPOP3ServerResponse( TheReturnString );
  2591.     { Put result in progress and status line }
  2592.     AddProgressText( TheReturnString );
  2593.     ShowProgressText( TheReturnString + #13#10 );
  2594.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  2595.   POP3CommandInProgress := false;
  2596.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  2597.   begin
  2598.     { Do clever C formatting trick }
  2599.     TheReturnString :=
  2600.      DoCStyleFormat( 'EMail Host Connection Failed!' ,
  2601.       [ nil ] );
  2602.     { Put result in progress and status line }
  2603.     AddProgressText( TheReturnString );
  2604.     ShowProgressErrorText( TheReturnString );
  2605.     { Signal error }
  2606.     Result := False;
  2607.     { leave }
  2608.     exit;
  2609.   end
  2610.   else Result := true; { Signal no problem }
  2611. end;
  2612.  
  2613. { This is the POP3 components QUIT routine }
  2614. function TPOP3SMTPComponent.SMTPDisconnect : Boolean;
  2615. var TheReturnString : String;  { Internal string holder }
  2616.     TheResult       : Integer; { Internal int holder    }
  2617. begin
  2618.   TheReturnString :=
  2619.    DoCStyleFormat( 'QUIT' ,
  2620.     [ nil ] );
  2621.   { Put result in progress and status line }
  2622.   AddProgressText( TheReturnString );
  2623.   ShowProgressText( TheReturnString );
  2624.   { Begin login sequence with user name }
  2625.   PerformSMTPCommand( 'QUIT', [ nil ] );
  2626.   repeat
  2627.     TheResult := GetSMTPServerResponse( TheReturnString );
  2628.     { Put result in progress and status line }
  2629.     AddProgressText( TheReturnString );
  2630.     ShowProgressText( TheReturnString + #13#10 );
  2631.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  2632.   SMTPCommandInProgress := false;
  2633.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  2634.   begin
  2635.     { Do clever C formatting trick }
  2636.     TheReturnString :=
  2637.      DoCStyleFormat( 'EMail Host Connection Failed!' ,
  2638.       [ nil ] );
  2639.     { Put result in progress and status line }
  2640.     AddProgressText( TheReturnString );
  2641.     ShowProgressErrorText( TheReturnString );
  2642.     { Signal error }
  2643.     Result := False;
  2644.     { leave }
  2645.     exit;
  2646.   end
  2647.   else Result := true; { Signal no problem }
  2648. end;
  2649.  
  2650. procedure TPOP3SMTPComponent.UpdateGauge( BytesFinished , TotalToHandle : longint );
  2651. begin
  2652.   CCInetCCForm.UpdateMailGauge( BytesFinished , TotalToHandle );
  2653. end;
  2654.  
  2655. end.
  2656.